Merge pull request 'API для рецептов просеивания' (#1) from siev_rec into mtsr_devel
Reviewed-on: #1
This commit is contained in:
commit
a45344bfb0
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "techage"]
|
||||
path = techage
|
||||
url = https://git.luanti.ru/MTSR/techage
|
1
techage
Submodule
1
techage
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e33bf6050a6f75dd1aa6c551eb389f0dd5228124
|
@ -1,112 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
GPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Demo for a electrical power consuming node
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = minetest.pos_to_string
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local PWR_NEEDED = 5
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local Cable = techage.ElectricCable
|
||||
--local Cable = techage.Axle
|
||||
local power = networks.power
|
||||
|
||||
local function swap_node(pos, name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == name then
|
||||
return
|
||||
end
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not nvm.running and power.power_available(pos, Cable) then
|
||||
nvm.running = true
|
||||
swap_node(pos, "techage:sink_on")
|
||||
M(pos):set_string("infotext", "on")
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
else
|
||||
nvm.running = false
|
||||
swap_node(pos, "techage:sink")
|
||||
M(pos):set_string("infotext", "off")
|
||||
minetest.get_node_timer(pos):stop()
|
||||
end
|
||||
end
|
||||
|
||||
local function after_place_node(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("infotext", "off")
|
||||
Cable:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
Cable:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:sink", {
|
||||
description = "Sink",
|
||||
tiles = {'techage_electric_button.png^[colorize:#000000:50'},
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
|
||||
if consumed == PWR_NEEDED then
|
||||
swap_node(pos, "techage:sink_on")
|
||||
M(pos):set_string("infotext", "on")
|
||||
end
|
||||
return true
|
||||
end,
|
||||
on_rightclick = on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
|
||||
paramtype = "light",
|
||||
light_source = 0,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy = 2, cracky = 2, crumbly = 2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:sink_on", {
|
||||
description = "Sink",
|
||||
tiles = {'techage_electric_button.png'},
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
|
||||
if consumed < PWR_NEEDED then
|
||||
swap_node(pos, "techage:sink")
|
||||
M(pos):set_string("infotext", "off")
|
||||
end
|
||||
return true
|
||||
end,
|
||||
on_rightclick = on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
|
||||
paramtype = "light",
|
||||
light_source = minetest.LIGHT_MAX,
|
||||
paramtype2 = "facedir",
|
||||
diggable = false,
|
||||
drop = "",
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
power.register_nodes({"techage:sink", "techage:sink_on"}, Cable, "con")
|
@ -1,43 +0,0 @@
|
||||
local M = minetest.get_meta
|
||||
|
||||
minetest.register_node("techage:testblock", {
|
||||
description = "Testblock",
|
||||
tiles = {
|
||||
"techage_top_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
is_ground_content = false,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.test_val = 1
|
||||
M(pos):set_int("test_val", 1)
|
||||
M(pos):set_string("infotext", "Value = " .. 1)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Update testblock",
|
||||
name = "techage:update_testblock",
|
||||
|
||||
nodenames = {
|
||||
"techage:testblock",
|
||||
},
|
||||
|
||||
run_at_every_load = true,
|
||||
|
||||
action = function(pos, node)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if M(pos):get_int("test_val") == nvm.test_val then
|
||||
nvm.test_val = nvm.test_val + 1
|
||||
M(pos):set_int("test_val", nvm.test_val)
|
||||
M(pos):set_string("infotext", "Value = " .. nvm.test_val)
|
||||
else
|
||||
minetest.log("error", "[techage] Memory error at " .. minetest.pos_to_string(pos))
|
||||
M(pos):set_string("infotext", "Error")
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
@ -1,662 +0,0 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 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.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero 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
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
TechAge, a mod to go through 5 tech ages in search of wealth and power.
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
@ -1,408 +0,0 @@
|
||||
# Tech Age [techage] (Minetest 5.4+)
|
||||
|
||||
Tech Age, a mod to go through 5 tech ages in search of wealth and power.
|
||||
|
||||
![screenshot](https://github.com/joe7575/techage/blob/master/screenshot.png)
|
||||
|
||||
|
||||
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 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.
|
||||
- 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.
|
||||
(no endless ore generation by means of cobble generators)
|
||||
|
||||
**Techage blocks store information outside of the block. This is for performance reasons.
|
||||
If you move, place, or remove blocks with any tool, at best, only the information is lost.
|
||||
In the worst case, the server crashes.**
|
||||
|
||||
[Manuals](https://github.com/joe7575/techage/wiki)
|
||||
|
||||
|
||||
### License
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt
|
||||
Textures: CC BY-SA 3.0
|
||||
|
||||
The TA1 mill sound is from https://freesound.org/people/JustinBW/sounds/70200/
|
||||
The TA1 watermill sound is from https://freesound.org/people/bmoreno/sounds/164182/
|
||||
|
||||
Many thanks to Thomas-S, niklp09, and others for their contributions
|
||||
|
||||
|
||||
### Dependencies
|
||||
Required: default, doors, bucket, stairs, screwdriver, basic_materials, tubelib2, networks, minecart, lcdlib, safer_lua, doclib
|
||||
Recommended: signs_bot, hyperloop, compost, techpack_stairway, autobahn
|
||||
Optional: unified_inventory, wielded_light, unifieddyes, lua-mashal, lsqlite3, moreores, ethereal, mesecon
|
||||
|
||||
|
||||
The mods `default`, `doors`, `bucket`, `stairs`, and `screwdriver` are part of Minetest Game.
|
||||
|
||||
`basic_materials` will be found here: https://content.minetest.net/
|
||||
|
||||
The following mods in the newest version have to be downloaded directly from GitHub:
|
||||
* [tubelib2](https://github.com/joe7575/tubelib2)
|
||||
* [networks](https://github.com/joe7575/networks)
|
||||
* [minecart](https://github.com/joe7575/minecart)
|
||||
* [lcdlib](https://github.com/joe7575/lcdlib)
|
||||
* [safer_lua](https://github.com/joe7575/safer_lua)
|
||||
* [doclib](https://github.com/joe7575/doclib)
|
||||
|
||||
It is highly recommended that you install the following mods, too:
|
||||
|
||||
* [signs_bot](https://github.com/joe7575/signs_bot): For many automation tasks in TA3/TA4 like farming, mining, and item transportation
|
||||
* [hyperloop](https://github.com/joe7575/Minetest-Hyperloop): Used as passenger transportation system in TA4
|
||||
* [compost](https://github.com/joe7575/compost): The garden soil is needed for the TA4 LED Grow Light based flower bed
|
||||
* [techpack_stairway](https://github.com/joe7575/techpack_stairway): Ladders, stairways, and bridges for your machines
|
||||
* [autobahn](https://github.com/joe7575/autobahn): Street blocks and slopes with stripes for faster traveling
|
||||
* [ta4_jetpack](https://github.com/joe7575/ta4_jetpack): A Jetpack with hydrogen as fuel and TA4 recipe
|
||||
|
||||
More recommended Techage related mods by other authors:
|
||||
|
||||
* [ta4_addons](https://github.com/Thomas--S/ta4_addons) from Thomas--S: A Touchscreen for the Lua controller
|
||||
* [ts_vehicles](https://github.com/Thomas--S/ts_vehicles) from Thomas--S: A mod to provide cars and other vehicles for Minetest.
|
||||
* [ta_apiary](https://gitlab.com/lesya_minetest_mods/ta_apiary) from Olesya Sibidanova: TechAge Machines for beekeeping
|
||||
|
||||
For large servers with many players, the following packages are recommended:
|
||||
|
||||
* lua-mashal for faster serialization/deserialization of data
|
||||
* lsqlite3 for storing node and network data
|
||||
|
||||
The packages have to be installed via [luarocks](https://luarocks.org/):
|
||||
|
||||
luarocks --lua-version 5.1 install lsqlite3
|
||||
luarocks --lua-version 5.1 install lua-marshal
|
||||
|
||||
To enable these `unsafe` packages, add 'techage' and 'lua-marshal'
|
||||
to the list of trusted mods in `minetest.conf`:
|
||||
|
||||
secure.trusted_mods = techage,lua-marshal
|
||||
|
||||
and add the following line to your `world.mt` or `minetest.conf`:
|
||||
|
||||
techage_use_sqlite = true
|
||||
|
||||
Available worlds will be converted to 'lsqlite3', but there is no way back, so:
|
||||
|
||||
**Never disable 'lsqlite3' for a world that has already been used!**
|
||||
|
||||
### History
|
||||
|
||||
**2023-11-05 V1.18**
|
||||
|
||||
- Add TA2 clutch
|
||||
- TA5 Generator: Add generator menu
|
||||
- TA4 Injector: Allow rotation with a screwdriver
|
||||
- Escape equal sign in german translation (Niklp09)
|
||||
- Autocrafter: Add Beduino command interface
|
||||
- Autocrafter: Add flush command
|
||||
- Fix converter stores mesecon signals (Niklp09)
|
||||
- TA1 Gravel Sieve: Use proper player creative check (Niklp09)
|
||||
- TA4 Chest: Add storesize command
|
||||
- Improve Assembly Tool
|
||||
- Furnace: Fix burn time issue
|
||||
- Allow further types of cobblestone for the coalburner
|
||||
- Fix water mill river water bug (alwayshopeless)
|
||||
- Improve manual
|
||||
- Further improvements
|
||||
|
||||
**2023-08-25 V1.17**
|
||||
|
||||
- Add support for doclib / remove techage internal doc support
|
||||
**The mod doclib is a new hard depenency !**
|
||||
- Fix LICENCSE file bug
|
||||
- Add beduino support for TA3 repeater (realmicu)
|
||||
- Add inv_name_prefix to `techage.register_consumer` (debiankaios)
|
||||
- Add generator menu to TA5 generator (fusion reactor)
|
||||
- Adapt mod to the new lcdlib mod
|
||||
- Fix some bugs
|
||||
|
||||
**2023-06-30 V1.16**
|
||||
|
||||
- Add TA4 node detector
|
||||
- Add wrench menu to TA3 button
|
||||
- Add arrows to the pump bottom and allow to turn the pump with the Techage Screwdriver
|
||||
- Fix bug with configurred TA4 chest and TA5 teleport tubes
|
||||
- Add gaze sensor
|
||||
- Many bugfixes and improvements
|
||||
|
||||
**2023-05-05 V1.15**
|
||||
|
||||
- Allow energy storage with up to 13x13x13 concrete blocks
|
||||
- Allow registration of other buckets
|
||||
- Add hyperloop chest only if the hyperloop mod is available
|
||||
- Add missing 'minetest.formspec_escape' #131
|
||||
- Fix bug "Trouble with flycontroller #130"
|
||||
- Add optional dependency on farming mod (orwell96)
|
||||
- Fix forceload formspec receiver (Niklp09)
|
||||
|
||||
**2023-04-16 V1.14**
|
||||
|
||||
- Add file "api.md"
|
||||
- Add API function `register_ore_for_gravelsieve`
|
||||
- Add support for the game Asuna
|
||||
- Merge pull request #124 from Niklp09/drops
|
||||
- Fix keep node number issue
|
||||
- Fix manual issue #123
|
||||
|
||||
**2023-04-10 V1.13**
|
||||
|
||||
- Add "Teleport mode" to the ta5 fly controller
|
||||
|
||||
**2023-04-01 V1.12**
|
||||
|
||||
- Improve Transformer:
|
||||
- add wrench menu for 'max. power passed through'
|
||||
- Increase max. power passed through from 100 to 300 ku
|
||||
- Improve Electricmeter:
|
||||
- add wrench menu for 'max. power passed through' and 'power countdown' 2458
|
||||
- add commands to read the countdown value (Lua and Beduino controller)
|
||||
- Improve TA3 Mesecons Converter:
|
||||
- fix overload bug
|
||||
- fix missing dominant 'on' issue
|
||||
- Add version command to TA3/TA4 Terminal
|
||||
- TA5 Hyperloop Chest: Disable inventory access on client side due to minetest core issues
|
||||
|
||||
**2023-03-05 V1.11**
|
||||
|
||||
- Reduce the number of necessary exp points for TA5 Hyperloop Chest,
|
||||
TA5 Hyperloop Tank, and TA5 AI Chip II
|
||||
- Fix possible kernel crashes with TA5 Hyperloop Chest and autocrafter
|
||||
- Rework doorcontroller (menu changed)
|
||||
- Increase tank cart storage size to 200 units
|
||||
- Fix several paramtype/use_texture_alpha issues
|
||||
- Add command 'load' to the TA4 power terminal
|
||||
- Add beduino tank commands
|
||||
- Fix power consumption bug for a stopped collider
|
||||
- Fix electrolyzer formspec bug
|
||||
- Add Rack and pinion node
|
||||
- Expand ta4 sequencer wrench menu
|
||||
- Accept mincart carts for the move controller
|
||||
- movecontroller: Allow to move objects 'without' a move block
|
||||
- Add empty_spool as fab output
|
||||
- Fix doser goes blocked bug
|
||||
|
||||
**2023-02-04 V1.10**
|
||||
- Improve flycontroller
|
||||
- Remove handover for movecontroller
|
||||
- Rename "techage:signal_lamp" to "techage:color_lamp"
|
||||
- Rename "techage:signal_lamp2" to "techage:color_lamp2"
|
||||
- Add countdown mode to TA4 Detector
|
||||
- Adapt to new beduino and minecart versions
|
||||
- Improve manuals
|
||||
- flycontroller/movecontroller: Allow moving blocks through unloaded areas
|
||||
- playerdetector: Add wrench menu to configure search radius
|
||||
- Default furnace: Don't use items filled from the top as fuel
|
||||
- Many further improvements and bug fixes from joe7575 and Niklp09
|
||||
|
||||
**2022-09-03 V1.09**
|
||||
- Change the way items are pushed
|
||||
- Add "Flow Limiter" mode to TA4 pump and TA4 pusher
|
||||
|
||||
**2022-06-06 V1.08**
|
||||
- Native support for the mod Beduino added
|
||||
|
||||
**2022-01-22 V1.07**
|
||||
- TA5 fusion reactor added
|
||||
|
||||
**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
|
||||
- Add techage command counting function to be able to limit the amount of commands/min.
|
||||
- Pull request #67: Add switch mode for 4x Button (by realmicu)
|
||||
- Pull request #69: Add option to keep assignment for TA4 Tank (by Thomas-S)
|
||||
|
||||
**2021-09-18 V1.02**
|
||||
- TA4 Chest: Fix items disappearing (PR #64 by Thomas--S)
|
||||
- Add support for colored cables (PR #63 by Thomas--S)
|
||||
|
||||
**2021-08-16 V1.01**
|
||||
- Allow singleplayer to place lava on y>0.
|
||||
- Logic block: allow to use output numbers for the expression
|
||||
- Pull request #60: Allow to pause the sequencer with a TechAge command (by Thomas-S)
|
||||
- Pull request #61: Allow sharing the button based on protection (by Thomas-S)
|
||||
- Pull request #62: Allow picking TA3 Tiny Generator with fuel (by realmicu)
|
||||
- Add TA1 watermill
|
||||
- Fix TA4 LED Grow Light bug
|
||||
- Fix grinder recipe bu
|
||||
|
||||
**2021-07-23 V1.00**
|
||||
- Change the way, power distribution works
|
||||
- Add TA2 storage system
|
||||
- Add TA4 Isolation Transformer
|
||||
- Add TA4 Electric Meter
|
||||
- Add new power terminal
|
||||
- Many improvements on power producing/consuming nodes
|
||||
- See Construction Board for some hints on moving to v1
|
||||
|
||||
**2021-05-14 V0.26**
|
||||
- Add concentrator tubes
|
||||
- Add ta4 cable wall entry
|
||||
- Pull request #57: Distributor improvements (from Thomas-S)
|
||||
- Add new power terminal commands
|
||||
- Add new door controller
|
||||
- Add laser beam nodes for energy transfer
|
||||
- Add TA4 recycle machine
|
||||
- Many improvements and bug fixes
|
||||
|
||||
**2020-11-01 V0.25**
|
||||
- Pull request #37: Trowel: Add protection support (from Thomas-S)
|
||||
- Pull request #38: Charcoal Pile: Ignore "ignore" nodes (from Thomas-S)
|
||||
- Autocrafter: Add register function for uncraftable items
|
||||
- Fix bug: Tubes do not recognize when TA2 nodes are added/removed
|
||||
- TA4 chest/tank: Add 'public' checkbox to allow public access
|
||||
- Add nodes TA2 Power Generator and TA3 Electric Motor
|
||||
|
||||
**2020-10-20 V0.24**
|
||||
- Pull request #27: Liquid Tanks: Add protection support (from Thomas-S)
|
||||
- Pull request #28: Quarry: Improve digging behaviour (from Thomas-S)
|
||||
- Pull request #29: Distributor: Keep metadata (from Thomas-S)
|
||||
- Pull request #30: TA4: Add Liquid Filter (from Thomas-S)
|
||||
- Pull request #31: Fix chest crash (from Thomas-S)
|
||||
- Pull request #32: Fix Filter Sink Bug (from Thomas-S)
|
||||
- Pull request #33: Add TA4 High Performance Distributor (from Thomas-S)
|
||||
- Pull request #34: Add TA4 High Performance Distributor to Hopper (from Thomas-S)
|
||||
- Pull request #35: Fixed Gravel Sieve bug (from CosmicConveyor)
|
||||
- Fix doorcontroller and ta4 doser bugs
|
||||
- Add check for wind turbine areas
|
||||
- Fix translation errors
|
||||
- QSG: Add power consumptions and fix manual bug
|
||||
- Add load command to the controller battery
|
||||
- TA4 silo: Add load command
|
||||
- silo/tank: Add second return value for load command
|
||||
- Liquid Pumps: Fix issue with undetected pipe connection gaps
|
||||
- Shrink PGN files
|
||||
- Fix ta4 chest bugs
|
||||
- Fix ta4 chest and ta3 firebox issues
|
||||
- Remove repairkit recipe
|
||||
- Switched to AGPL license
|
||||
- API added for ingame manual
|
||||
|
||||
**2020-09-13 V0.23**
|
||||
- Pull request #26: Digtron Battery: Fix duplication bug (from Thomas-S)
|
||||
- Improve ta4 sensor box
|
||||
- Firebox: Add check for free space when placing the node
|
||||
- Lua controller: Add 'get_gametime' function
|
||||
- Pull request #27: Liquid Tanks: Add protection support (from Thomas-S)
|
||||
- Fix pump issue (silo source items can disappear)
|
||||
- Pull request #28: Quarry: Improve digging behaviour (from Thomas-S)
|
||||
- Pull request #28: Battery: Store battery load as metadata (from Thomas-S)
|
||||
- Pull request #29: Distributor: Keep item metadata (from Thomas-S)
|
||||
|
||||
**2020-08-08 V0.22**
|
||||
- Pull request #25: Growlight: Improve flower registration (from Thomas-S)
|
||||
- Add tube support for digtron chests and protector:chest
|
||||
|
||||
**2020-08-08 V0.21**
|
||||
- Pull request #18: Add a simple Digtron battery (from Thomas-S)
|
||||
- Pull request #23: Lua Controller: Fix $item_description() documentation and translation (from Thomas-S)
|
||||
- Pull request #24: Distributor: improve fairness by using random spread (from realmicu)
|
||||
- Bugfix: TA1 meridian hammer did not glow (from realmicu)
|
||||
- Bugfix: power.power_available() did not check the network state
|
||||
|
||||
**2020-07-31 V0.20**
|
||||
- Pull request #21: Lua Controller: Allow to get itemstring and description of 8x2000 chest contents (from Thomas-S)
|
||||
- Pull request #22: Trowel: Prevent hidden nodes from being dug (from Thomas-S)
|
||||
- Improvement: TA3 Power Terminal: Outputs max needed power in addition
|
||||
- Bugfix: Quarry: Shall not dig Techage Light Blocks
|
||||
|
||||
**2020-07-24 V0.19**
|
||||
- Pull request #19: Refactor ICTA to use functions instead of loadstring (from Thomas-S)
|
||||
- State command added for cart-, node-, and player detectors
|
||||
|
||||
**2020-07-21 V0.18**
|
||||
- Pull request #13: Use Monospace Font for Code-Related Formspecs (from Thomas-S)
|
||||
- Pull request #14: Don't allow to put items with meta or wear information into the 8x2000 chest (from Thomas-S)
|
||||
- Pull request #15: Blackhole: Add support for liquids (from Thomas-S)
|
||||
- Pull request #16: ICTA Controller: Add support for valves by adding on/off states (from Thomas-S)
|
||||
- Bugfix: Digging Redstone gives an 'unknown block'
|
||||
- ICTA Controller: Escape quotation marks for text outputs
|
||||
|
||||
**2020-07-16 V0.17**
|
||||
- TA4 Reactor recipe bugfix
|
||||
- TA3 furnace power bugfix (response to the pull request #12 from Thomas-S)
|
||||
- Manual bugfix (Thomas-S)
|
||||
- Charcoal pile doesn't start smoking after beeing unloaded (issue #9 from Skamiz)
|
||||
|
||||
**2020-07-06 V0.16**
|
||||
- Oil cracking/hydrogenation recipes added
|
||||
- Ethereal growlight bugfix
|
||||
- Charcoal pile bugfix (issue #9) Thanks to Skamiz
|
||||
- Quarry bugfix (pull request #10) Thanks to programmerjake
|
||||
|
||||
**2020-07-02 V0.15**
|
||||
- pipe valve added
|
||||
- growlight bugfix
|
||||
- further textures to gate/door blocks added
|
||||
- cement recipe bugfix
|
||||
- manual improvements
|
||||
|
||||
**2020-06-29 V0.14**
|
||||
- quarry sound bugfix
|
||||
- grinder bugfix
|
||||
- ore probability calculation changed
|
||||
- lua-marshal deactivated (due to weird server crashes)
|
||||
- alternative cement recipe added
|
||||
- aluminum output increased
|
||||
- reboiler cycle time increased to 16 s (from 6)
|
||||
- many manual improvements
|
||||
|
||||
**2020-06-19 V0.13**
|
||||
- Mesecons Converter added
|
||||
|
||||
**2020-06-17 V0.12**
|
||||
- Ethereal support added
|
||||
- manual correction
|
||||
- tin ingot recipe bugfix
|
||||
|
||||
**2020-06-14 V0.11**
|
||||
- cart commands added for both controllers
|
||||
- support for moreores added
|
||||
|
||||
**2020-06-04 V0.10**
|
||||
- minor changes and bugfixes
|
||||
|
||||
**2020-05-31 V0.09**
|
||||
- TA4 tubes upgraded, manuals updated
|
||||
|
||||
**2020-05-22 V0.08**
|
||||
- Support for 'lua-marshal' and 'lsqlite3' added
|
||||
|
||||
**2020-04-26 V0.07**
|
||||
- English translation added
|
||||
|
||||
**2020-04-24 V0.06**
|
||||
- TA4 injector added
|
||||
|
||||
**2020-03-14 V0.05**
|
||||
- TA4 Lua controller added
|
||||
|
||||
**2020-02-29 V0.04**
|
||||
- TA4 ICTA controller added
|
||||
|
||||
**2019-09-28 V0.02**
|
||||
- TA3 finished
|
||||
|
||||
**2019-06-16 V0.01**
|
||||
- First upload
|
@ -1 +0,0 @@
|
||||
theme: jekyll-theme-leap-day
|
225
techage/api.md
225
techage/api.md
@ -1,225 +0,0 @@
|
||||
# Techage API Functions
|
||||
|
||||
Techage API function to adapt/prepare techage for other mods/games.
|
||||
|
||||
|
||||
|
||||
## Move/Fly Controller
|
||||
|
||||
Register node names for nodes allowed to be moved by fly/move controllers.
|
||||
|
||||
This is only necessary for undiggable/intelligent nodes with one of the following attributes:
|
||||
|
||||
- ```drop = ""```
|
||||
- ```diggable = false```
|
||||
- ```after_dig_node ~= nil```
|
||||
|
||||
```lua
|
||||
techage.register_simple_nodes(node_names, is_valid)
|
||||
```
|
||||
|
||||
- `is_valid = true` - Add node to the list of simple nodes
|
||||
- `is_valid = false` - Remove node from the list of simple nodes
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
techage.register_simple_nodes({"techage:power_lineS"}, true)
|
||||
```
|
||||
|
||||
For door nodes used as sliding doors by means of the move controller, call in addition:
|
||||
|
||||
```lua
|
||||
techage.flylib.protect_door_from_being_opened(node_name)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA1 Hammer
|
||||
|
||||
Register stone/gravel name pair for the hammer blow:
|
||||
|
||||
```lua
|
||||
techage.register_stone_gravel_pair(stone_name, gravel_name)
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
techage.register_stone_gravel_pair("default:stone", "default:gravel")
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA1 Melting Pot
|
||||
|
||||
Register a pot recipe:
|
||||
|
||||
```lua
|
||||
techage.ironage_register_recipe(recipe)
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```lua
|
||||
techage.ironage_register_recipe({
|
||||
output = "default:obsidian",
|
||||
recipe = {"default:cobble"},
|
||||
heat = 10, -- Corresponds to the tower height
|
||||
time = 8, -- Cooking time in seconds
|
||||
})
|
||||
techage.ironage_register_recipe({
|
||||
output = "default:bronze_ingot 4",
|
||||
recipe = {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot", "default:tin_ingot"},
|
||||
heat = 4, -- Corresponds to the tower height
|
||||
time = 8, -- Cooking time in seconds
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA2/TA3/TA4 Autocrafter
|
||||
|
||||
Register any nodes/items that should not be crafted via the autocrafter.
|
||||
|
||||
```lua
|
||||
techage.register_uncraftable_items(item_name)
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA2/TA3/TA4 Gravel Sieve
|
||||
|
||||
Change the probability of ores or register new ores for sieving.
|
||||
|
||||
```lua
|
||||
techage.register_ore_for_gravelsieve(ore_name, probability)
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
techage.register_ore_for_gravelsieve("default:iron_lump", 30)
|
||||
```
|
||||
|
||||
Default values for MTG are:
|
||||
|
||||
```lua
|
||||
-- higher value means less frequent occurrence
|
||||
techage:baborium_lump 100000 -- hardly ever
|
||||
default:mese_crystal 548 -- every 548th time
|
||||
default:gold_lump 439
|
||||
default:tin_lump 60
|
||||
default:diamond 843
|
||||
default:copper_lump 145
|
||||
default:coal_lump 11
|
||||
default:iron_lump 15
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA2/TA3/TA4 Gravel Rinser
|
||||
|
||||
Add a rinser recipe.
|
||||
|
||||
```lua
|
||||
techage.add_rinser_recipe(recipe)
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
techage.add_rinser_recipe({input = "techage:sieved_gravel", output = "techage:usmium_nuggets", probability = 30})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA2/TA3/TA4 Grinder
|
||||
|
||||
Add a grinder recipe.
|
||||
|
||||
```lua
|
||||
techage.add_grinder_recipe(recipe, ta1_permitted)
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```lua
|
||||
echage.add_grinder_recipe({input = "default:cobble", output = "default:gravel"})
|
||||
techage.add_grinder_recipe({input = "default:sandstone", output = "default:sand 4"})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA3/TA4 Electronic Fab, TA4 Doser
|
||||
|
||||
Add recipes to an electronic fab or doser (chemical reactor):
|
||||
|
||||
|
||||
```lua
|
||||
techage.recipes.add(rtype, recipe)
|
||||
```
|
||||
|
||||
`rtype` is one of: `ta2_electronic_fab` , `ta4_doser`
|
||||
|
||||
A recipe look like:
|
||||
|
||||
```
|
||||
{
|
||||
output = "<item-name> <units>", -- units = 1..n
|
||||
waste = "<item-name> <units>", -- units = 1..n
|
||||
input = { -- up to 4 items
|
||||
"<item-name> <units>",
|
||||
"<item-name> <units>",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```lua
|
||||
techage.recipes.add("ta2_electronic_fab", {
|
||||
output = "techage:vacuum_tube 2",
|
||||
waste = "basic_materials:empty_spool 1",
|
||||
input = {"default:glass 1", "basic_materials:copper_wire 1", "basic_materials:plastic_sheet 1", "techage:usmium_nuggets 1"}
|
||||
})
|
||||
|
||||
techage.recipes.add("ta4_doser", {
|
||||
output = "techage:naphtha 1",
|
||||
input = {
|
||||
"techage:fueloil 1",
|
||||
},
|
||||
catalyst = "techage:gibbsite_powder",
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## TA3 Furnace
|
||||
|
||||
Register recipe:
|
||||
|
||||
```lua
|
||||
techage.furnace.register_recipe(recipe)
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```lua
|
||||
techage.furnace.register_recipe({
|
||||
output = "default:bronze_ingot 4",
|
||||
recipe = {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot", "default:tin_ingot"},
|
||||
time = 2, -- in seconds
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Assembly Tool
|
||||
|
||||
Disable a block from being removed by the assembly tool:
|
||||
|
||||
```lua
|
||||
techage.disable_block_for_assembly_tool(block_name)
|
||||
```
|
||||
|
@ -1,556 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
The autocrafter is derived from pipeworks:
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> WTFPL
|
||||
|
||||
TA2/TA3/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
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local UncraftableItems = {}
|
||||
|
||||
-- Add all nodes/items which should not be crafted with the autocrafter
|
||||
function techage.register_uncraftable_items(item_name)
|
||||
UncraftableItems[item_name] = true
|
||||
end
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,9.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;recipe;0,0;3,3;]"..
|
||||
"image[2.9,1;1,1;techage_form_arrow.png]"..
|
||||
"image[3.8,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"list[context;output;3.8,1;1,1;]"..
|
||||
"image_button[3.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.8,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;src;0,3.2;8,2;]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,5.4;8,4;]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;dst]" ..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 5.4)
|
||||
end
|
||||
|
||||
local function count_index(invlist)
|
||||
local index = {}
|
||||
for _, stack in pairs(invlist) do
|
||||
if not stack:is_empty() then
|
||||
local stack_name = stack:get_name()
|
||||
index[stack_name] = (index[stack_name] or 0) + stack:get_count()
|
||||
end
|
||||
end
|
||||
return index
|
||||
end
|
||||
|
||||
local function flush_input_inventory(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if not inv:is_empty("src") then
|
||||
for idx = 1, 16 do
|
||||
local stack = inv:get_stack("src", idx)
|
||||
if not inv:room_for_item("dst", stack) then
|
||||
return false
|
||||
end
|
||||
inv:add_item("dst", stack)
|
||||
inv:set_stack("src", idx, nil)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- caches some recipe data
|
||||
local autocrafterCache = {}
|
||||
|
||||
local function get_craft(pos, inventory, hash)
|
||||
hash = hash or minetest.hash_node_position(pos)
|
||||
local craft = autocrafterCache[hash]
|
||||
if not craft then
|
||||
local recipe = inventory:get_list("recipe")
|
||||
local output, decremented_input = minetest.get_craft_result(
|
||||
{method = "normal", width = 3, items = recipe})
|
||||
|
||||
-- check if registered item
|
||||
if UncraftableItems[output.item:get_name()] then
|
||||
output.item = ItemStack()
|
||||
end
|
||||
|
||||
craft = {recipe = recipe, consumption = count_index(recipe),
|
||||
output = output, decremented_input = decremented_input}
|
||||
autocrafterCache[hash] = craft
|
||||
end
|
||||
return craft
|
||||
end
|
||||
|
||||
local function autocraft(pos, crd, nvm, inv)
|
||||
local craft = get_craft(pos, inv)
|
||||
if not craft then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
local output_item = craft.output.item
|
||||
if output_item:get_name() == "" then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
|
||||
-- check if we have enough room in dst
|
||||
if not inv:room_for_item("dst", output_item) then
|
||||
crd.State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
local consumption = craft.consumption
|
||||
local inv_index = count_index(inv:get_list("src"))
|
||||
-- check if we have enough material available
|
||||
for itemname, number in pairs(consumption) do
|
||||
if (not inv_index[itemname]) or inv_index[itemname] < number then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- consume material
|
||||
for itemname, number in pairs(consumption) do
|
||||
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max
|
||||
inv:remove_item("src", ItemStack(itemname))
|
||||
end
|
||||
end
|
||||
|
||||
-- craft the result into the dst inventory and add any "replacements" as well
|
||||
inv:add_item("dst", output_item)
|
||||
for i = 1, 9 do
|
||||
inv:add_item("dst", craft.decremented_input.items[i])
|
||||
end
|
||||
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
autocraft(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
-- note, that this function assumes allready being updated to virtual items
|
||||
-- and doesn't handle recipes with stacksizes > 1
|
||||
local function after_recipe_change(pos, inventory)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
-- if we emptied the grid, there's no point in keeping it running or cached
|
||||
if inventory:is_empty("recipe") then
|
||||
autocrafterCache[minetest.hash_node_position(pos)] = nil
|
||||
inventory:set_stack("output", 1, "")
|
||||
crd.State:stop(pos, nvm)
|
||||
return
|
||||
end
|
||||
local recipe = inventory:get_list("recipe")
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local craft = autocrafterCache[hash]
|
||||
|
||||
if craft then
|
||||
-- check if it changed
|
||||
local cached_recipe = craft.recipe
|
||||
for i = 1, 9 do
|
||||
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
|
||||
autocrafterCache[hash] = nil -- invalidate recipe
|
||||
craft = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
craft = craft or get_craft(pos, inventory, hash)
|
||||
local output_item = craft.output.item
|
||||
inventory:set_stack("output", 1, output_item)
|
||||
crd.State:stop(pos, nvm)
|
||||
end
|
||||
|
||||
-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid
|
||||
-- if minetest supports query by group one day, this might replace them
|
||||
-- with a canonical version instead
|
||||
local function normalize(item_list)
|
||||
for i = 1, #item_list do
|
||||
local name = item_list[i]
|
||||
if not minetest.registered_items[name] then
|
||||
item_list[i] = ""
|
||||
end
|
||||
end
|
||||
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", {})
|
||||
inventory:set_list("recipe", {})
|
||||
else
|
||||
local input = minetest.get_craft_recipe(stack:get_name())
|
||||
if not input.items or input.type ~= "normal" then return end
|
||||
local items, width = normalize(input.items), input.width
|
||||
local item_idx, width_idx = 1, 1
|
||||
for i = 1, 9 do
|
||||
if width_idx <= width then
|
||||
inventory:set_stack("recipe", i, items[item_idx])
|
||||
item_idx = item_idx + 1
|
||||
else
|
||||
inventory:set_stack("recipe", i, ItemStack(""))
|
||||
end
|
||||
width_idx = (width_idx < 3) and (width_idx + 1) or 1
|
||||
end
|
||||
-- we'll set the output slot in after_recipe_change to the actual result of the new recipe
|
||||
end
|
||||
after_recipe_change(pos, inventory)
|
||||
end
|
||||
|
||||
local function determine_recipe_items(pos, input)
|
||||
local num, idx
|
||||
|
||||
if input and type(input) == "string" then -- Lua controller
|
||||
-- Test if "<node-number>.<recipe-number>" input
|
||||
num, idx = unpack(string.split(input, ".", false, 1))
|
||||
elseif input and type(input) == "table" then -- Beduino
|
||||
num = tostring(input[1] * 65536 + input[2])
|
||||
idx = tostring(input[3])
|
||||
end
|
||||
|
||||
if num and idx then
|
||||
input = get_input_from_recipeblock(pos, num, idx)
|
||||
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)
|
||||
local inv = M(pos):get_inventory()
|
||||
if items then
|
||||
for i = 1, 9 do
|
||||
inv:set_stack("recipe", i, items[i])
|
||||
end
|
||||
else
|
||||
inv:set_list("recipe", {})
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
autocrafterCache[hash] = nil
|
||||
local craft = get_craft(pos, inv, hash)
|
||||
if craft.output and craft.output.item then
|
||||
inv:set_stack("output", 1, craft.output.item)
|
||||
else
|
||||
inv:set_stack("output", 1, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if listname == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
if listname == "recipe" then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
elseif listname == "output" then
|
||||
on_output_change(pos, inv, stack)
|
||||
return 0
|
||||
elseif listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if listname == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
-- upgrade_autocrafter(pos)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if listname == "recipe" then
|
||||
inv:set_stack(listname, index, ItemStack(""))
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
elseif listname == "output" then
|
||||
on_output_change(pos, inv, nil)
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if from_list == "output" or "to_list" == "output" then
|
||||
return 0
|
||||
end
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
|
||||
if to_list == "output" then
|
||||
on_output_change(pos, inv, stack)
|
||||
return 0
|
||||
elseif from_list == "output" then
|
||||
on_output_change(pos, inv, nil)
|
||||
if to_list ~= "recipe" then
|
||||
return 0
|
||||
end -- else fall through to recipe list handling
|
||||
end
|
||||
|
||||
if from_list == "recipe" or to_list == "recipe" then
|
||||
if from_list == "recipe" then
|
||||
inv:set_stack(from_list, from_index, ItemStack(""))
|
||||
end
|
||||
if to_list == "recipe" then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(to_list, to_index, stack)
|
||||
end
|
||||
after_recipe_change(pos, inv)
|
||||
return 0
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_autocrafter.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_autocrafter4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local INFO = [[Commands: 'state', 'recipe']]
|
||||
|
||||
local tubing = {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
if access_type == "push" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
return meta:get_inventory(), "src"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "recipe" and CRD(pos).stage == 4 then
|
||||
if payload and payload ~= "" then
|
||||
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 == "flush" and CRD(pos).stage == 4 then
|
||||
return flush_input_inventory(pos)
|
||||
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_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 10 and CRD(pos).stage == 4 then
|
||||
on_new_recipe(pos, payload)
|
||||
return 1, ""
|
||||
elseif topic == 11 and CRD(pos).stage == 4 then
|
||||
if flush_input_inventory(pos) then
|
||||
return 1, ""
|
||||
else
|
||||
return 0, ""
|
||||
end
|
||||
end
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("autocrafter", S("Autocrafter"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 2*8)
|
||||
inv:set_size("recipe", 3*3)
|
||||
inv:set_size("dst", 3*3)
|
||||
inv:set_size("output", 1)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,4,6,9},
|
||||
},
|
||||
{false, true, true, true}) -- TA2/TA3/TA4
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:diamond", "group:wood"},
|
||||
{"techage:tubeS", "basic_materials:gear_steel", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
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", "techage:ta4_autocrafter_pas"}, function(pos, node)
|
||||
power.update_network(pos, nil, Cable)
|
||||
end)
|
@ -1,89 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
All items and liquids disappear.
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
|
||||
local function take_liquid(pos, indir, name, amount)
|
||||
return 0, name
|
||||
end
|
||||
|
||||
local function put_liquid(pos, indir, name, amount)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function peek_liquid(pos, indir)
|
||||
return nil
|
||||
end
|
||||
|
||||
minetest.register_node("techage:blackhole", {
|
||||
description = S("TechAge Black Hole"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png^techage_appl_hole_pipe.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png^techage_appl_inp.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_blackhole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
|
||||
meta:set_string("infotext", S("TechAge Black Hole (let items and liquids disappear)"))
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:blackhole",
|
||||
recipe = {
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"techage:tubeS", "default:coal_lump", "techage:ta3_pipeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:blackhole"}, {
|
||||
on_pull_item = nil, -- not needed
|
||||
on_unpull_item = nil, -- not needed
|
||||
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir then
|
||||
return true
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:blackhole"},
|
||||
Pipe, "tank", {"R"}, {
|
||||
capa = 9999999,
|
||||
peek = peek_liquid,
|
||||
put = put_liquid,
|
||||
take = take_liquid,
|
||||
}
|
||||
)
|
@ -1,463 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local TA4_INV_SIZE = 50
|
||||
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
local mConf = dofile(MP.."/basis/conf_inv.lua")
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function formspec2()
|
||||
return "size[9,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0.5,0;8,4;]"..
|
||||
"list[current_player;main;0.5,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta2", {
|
||||
description = S("TA2 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_front_ta3.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 32)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec2())
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA2 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
local function formspec3()
|
||||
return "size[10,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0,0;10,4;]"..
|
||||
"list[current_player;main;1,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta3", {
|
||||
description = S("TA3 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_back_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_chest_front_ta3.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 40)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.add_node(pos, "techage:chest_ta3")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec3())
|
||||
meta:set_string("infotext", S("TA3 Protected Chest").." "..number)
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA3 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:chest_ta2", "techage:chest_ta3"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
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
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_inv_state(inv, "main")
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
local function formspec4(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";1;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;0,0;10,5;]"..
|
||||
mConf.preassigned_stacks(pos, 10, 5)..
|
||||
"list[current_player;main;1,5.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function formspec4_pre(pos)
|
||||
return "size[10,9]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";2;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;conf;0,0;10,5;]"..
|
||||
"list[current_player;main;1,5.3;8,4;]"..
|
||||
"listring[context;conf]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function formspec4_cfg(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local label = meta:get_string("label") or ""
|
||||
local public = dump((meta:get_int("public") or 0) == 1)
|
||||
return "size[10,5]"..
|
||||
"tabheader[0,0;tab;"..S("Inventory,Pre-Assignment,Config")..";3;;true]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"field[0.5,1;9,1;label;"..S("Node label:")..";"..label.."]" ..
|
||||
"checkbox[1,2;public;"..S("Allow public access to the chest")..";"..public.."]"..
|
||||
"button_exit[3.5,4;3,1;exit;"..S("Save").."]"
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if listname == "main" then
|
||||
return stack:get_count()
|
||||
else
|
||||
return mConf.allow_conf_inv_put(pos, listname, index, stack, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if listname == "main" then
|
||||
return stack:get_count()
|
||||
else
|
||||
return mConf.allow_conf_inv_take(pos, listname, index, stack, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function ta4_allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if from_list == "main" then
|
||||
return count
|
||||
else
|
||||
return mConf.allow_conf_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_ta4", {
|
||||
description = S("TA4 Protected Chest"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 50)
|
||||
inv:set_size('conf', 50)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.add_node(pos, "techage:chest_ta4")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec4(pos))
|
||||
meta:set_string("infotext", S("TA4 Protected Chest").." "..number)
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if fields.tab == "1" then
|
||||
mem.filter = nil
|
||||
meta:set_string("formspec", formspec4(pos))
|
||||
elseif fields.tab == "2" then
|
||||
meta:set_string("formspec", formspec4_pre(pos))
|
||||
elseif fields.tab == "3" then
|
||||
meta:set_string("formspec", formspec4_cfg(pos))
|
||||
elseif fields.quit == "true" then
|
||||
mem.filter = nil
|
||||
end
|
||||
if fields.public then
|
||||
meta:set_int("public", fields.public == "true" and 1 or 0)
|
||||
end
|
||||
if fields.exit then
|
||||
local number = meta:get_string("node_number")
|
||||
if fields.label ~= "" then
|
||||
meta:set_string("infotext", minetest.formspec_escape(fields.label).." #"..number)
|
||||
else
|
||||
meta:set_string("infotext", S("TA4 Protected Chest").." "..number)
|
||||
end
|
||||
meta:set_string("label", fields.label)
|
||||
meta:set_string("formspec", formspec4_cfg(pos))
|
||||
end
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, S("TA4 Protected Chest"))
|
||||
end,
|
||||
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = ta4_allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = ta4_allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = ta4_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:chest_ta4"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if inv:is_empty("main") then
|
||||
return nil
|
||||
end
|
||||
|
||||
if item_name then
|
||||
if mem.filter[item_name] or not mem.chest_configured then
|
||||
local taken = inv:remove_item("main", {name = item_name, count = num})
|
||||
if taken:get_count() > 0 then
|
||||
return taken
|
||||
end
|
||||
end
|
||||
else -- no item given
|
||||
if mem.chest_configured then
|
||||
return mConf.take_item(pos, inv, "main", num, mem.filter["unconfigured"])
|
||||
else
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, item, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if mem.chest_configured then
|
||||
local name = item:get_name()
|
||||
local stacks = mem.filter[name] or mem.filter["unconfigured"]
|
||||
return mConf.put_items(pos, inv, "main", item, stacks, idx)
|
||||
else
|
||||
return techage.put_items(inv, "main", item, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, item)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
|
||||
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
|
||||
|
||||
if mem.chest_configured then
|
||||
local name = item:get_name()
|
||||
local stacks = mem.filter[name] or mem.filter["unconfigured"]
|
||||
return mConf.put_items(pos, inv, "main", item, stacks)
|
||||
else
|
||||
return techage.put_items(inv, "main", item)
|
||||
end
|
||||
end,
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "state" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_inv_state(inv, "main")
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"default:chest", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"default:chest_locked", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta2",
|
||||
recipe = {"protector:chest", "techage:tubeS", "techage:iron_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta3",
|
||||
recipe = {"techage:chest_ta2", "default:chest"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta4",
|
||||
recipe = {"techage:chest_ta3", "default:chest"}
|
||||
})
|
@ -1,154 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube Concentrator
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Tube = techage.Tube
|
||||
|
||||
local size = 2/8
|
||||
local Boxes = {
|
||||
{{-size, -size, size, size, size, 0.5 }}, -- z+
|
||||
{{-size, -size, -size, 0.5, size, size}}, -- x+
|
||||
{{-size, -size, -0.5, size, size, size}}, -- z-
|
||||
{{-0.5, -size, -size, size, size, size}}, -- x-
|
||||
{{-size, -0.5, -size, size, size, size}}, -- y-
|
||||
{{-size, -size, -size, size, 0.5, size}}, -- y+
|
||||
}
|
||||
|
||||
local names = networks.register_junction("techage:concentrator", 2/8, Boxes, Tube, {
|
||||
description = S("Tube Concentrator"),
|
||||
tiles = {
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tube_junction.png^techage_tube_hole.png",
|
||||
"techage_tube_junction.png",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR90",
|
||||
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
},
|
||||
paramtype2 = "facedir", -- important!
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1},
|
||||
sounds = default.node_sound_defaults(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local node = minetest.get_node(pos)
|
||||
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
|
||||
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
end,
|
||||
}, 27)
|
||||
|
||||
for _, name in ipairs(names) do
|
||||
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
|
||||
end
|
||||
|
||||
techage.register_node(names, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
if networks.Flip[push_dir] ~= in_dir then
|
||||
return techage.safe_push_items(pos, push_dir, stack)
|
||||
else
|
||||
return stack
|
||||
end
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
})
|
||||
|
||||
names = networks.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube, {
|
||||
description = S("TA4 Tube Concentrator"),
|
||||
tiles = {
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
"techage_tubeta4_junction.png^techage_tube_hole.png",
|
||||
"techage_tubeta4_junction.png",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR90",
|
||||
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
|
||||
},
|
||||
paramtype2 = "facedir", -- important!
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1},
|
||||
sounds = default.node_sound_defaults(),
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local node = minetest.get_node(pos)
|
||||
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
Tube:after_place_node(pos)
|
||||
end,
|
||||
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
|
||||
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
|
||||
minetest.swap_node(pos, {name = name, param2 = node.param2})
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
M(pos):set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_node(pos)
|
||||
end,
|
||||
}, 27)
|
||||
|
||||
for _, name in ipairs(names) do
|
||||
Tube:set_valid_sides(name, {"B", "R", "F", "L", "D", "U"})
|
||||
end
|
||||
|
||||
techage.register_node(names, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
if networks.Flip[push_dir] ~= in_dir then
|
||||
return techage.safe_push_items(pos, push_dir, stack)
|
||||
else
|
||||
return stack
|
||||
end
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:concentrator27",
|
||||
recipe = {
|
||||
{"", "techage:tubeS", ""},
|
||||
{"techage:tubeS", "", "techage:tubeS"},
|
||||
{"", "techage:tubeS", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_concentrator27",
|
||||
recipe = {
|
||||
{"", "techage:ta4_tubeS", ""},
|
||||
{"techage:ta4_tubeS", "", "techage:ta4_tubeS"},
|
||||
{"", "techage:ta4_tubeS", ""},
|
||||
},
|
||||
})
|
@ -1,314 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Consumer node basis functionality.
|
||||
It handles:
|
||||
- up to 4 stages of nodes (TA2/TA3/TA4/TA5)
|
||||
- power consumption
|
||||
- node state handling
|
||||
- registration of passive and active nodes
|
||||
- Tube connections are on left and right side (from left to right)
|
||||
- Power connection are on front and back side (front or back)
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local CRDN = function(node) return (minetest.registered_nodes[node.name] or {}).consumer end
|
||||
|
||||
local Tube = techage.Tube
|
||||
local power = networks.power
|
||||
local liquid = networks.liquid
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local function get_keys(tbl)
|
||||
local keys = {}
|
||||
for k,v in pairs(tbl) do
|
||||
keys[#keys + 1] = k
|
||||
end
|
||||
return keys
|
||||
end
|
||||
|
||||
local function has_power(pos, nvm, state)
|
||||
local crd = CRD(pos)
|
||||
return power.power_available(pos, crd.power_netw)
|
||||
end
|
||||
|
||||
local function start_node(pos, nvm, state)
|
||||
end
|
||||
|
||||
local function stop_node(pos, nvm, state)
|
||||
end
|
||||
|
||||
local function node_timer_pas(pos, elapsed)
|
||||
local crd = CRD(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
-- handle power consumption
|
||||
if crd.power_netw and techage.needs_power(nvm) then
|
||||
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
||||
if consumed == crd.power_consumption then
|
||||
crd.State:start(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- call the node timer routine
|
||||
if techage.is_operational(nvm) then
|
||||
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
||||
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
||||
crd.node_timer(pos, crd.cycle_time)
|
||||
nvm.node_timer_call_cyle = 0
|
||||
end
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function node_timer_act(pos, elapsed)
|
||||
local crd = CRD(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
-- handle power consumption
|
||||
if crd.power_netw and techage.needs_power(nvm) then
|
||||
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
|
||||
if consumed < crd.power_consumption then
|
||||
crd.State:nopower(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- call the node timer routine
|
||||
if techage.is_operational(nvm) then
|
||||
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
|
||||
if nvm.node_timer_call_cyle >= crd.call_cycle then
|
||||
crd.node_timer(pos, crd.cycle_time)
|
||||
nvm.node_timer_call_cyle = 0
|
||||
end
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function prepare_tiles(tiles, stage, power_png)
|
||||
local tbl = {}
|
||||
for _,item in ipairs(tiles) do
|
||||
if type(item) == "string" then
|
||||
tbl[#tbl+1] = item:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
||||
else
|
||||
local temp = table.copy(item)
|
||||
temp.name = temp.name:gsub("#", stage):gsub("{power}", power_png):gsub("@@", '#')
|
||||
tbl[#tbl+1] = temp
|
||||
end
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
-- 'validStates' is optional and can be used to e.g. enable
|
||||
-- only one TA2 node {false, true, false, false}
|
||||
function techage.register_consumer(base_name, inv_name, tiles, tNode, validStates, node_name_prefix, inv_name_prefix)
|
||||
local names = {}
|
||||
validStates = validStates or {true, true, true, true}
|
||||
|
||||
node_name_prefix = node_name_prefix or "techage:ta"
|
||||
if inv_name_prefix then
|
||||
inv_name_prefix = inv_name_prefix.." "
|
||||
else
|
||||
inv_name_prefix = ""
|
||||
end
|
||||
|
||||
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 = inv_name_prefix.."TA"..stage.." "..inv_name
|
||||
names[#names+1] = name_pas
|
||||
|
||||
if validStates[stage] then
|
||||
local power_network
|
||||
local power_png = 'techage_axle_clutch.png'
|
||||
local power_used = tNode.power_consumption ~= nil
|
||||
local sides
|
||||
-- power needed?
|
||||
if power_used then
|
||||
if stage > 2 then
|
||||
power_network = techage.ElectricCable
|
||||
power_png = 'techage_appl_hole_electric.png'
|
||||
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
||||
else
|
||||
power_network = techage.Axle
|
||||
power_png = 'techage_axle_clutch.png'
|
||||
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
|
||||
end
|
||||
end
|
||||
|
||||
local tState = techage.NodeStates:new({
|
||||
node_name_passive = name_pas,
|
||||
node_name_active = name_act,
|
||||
infotext_name = name_inv,
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = tNode.standby_ticks,
|
||||
formspec_func = tNode.formspec,
|
||||
on_state_change = tNode.on_state_change,
|
||||
can_start = tNode.can_start,
|
||||
quick_start = tNode.quick_start,
|
||||
has_power = tNode.has_power or power_used and has_power or nil,
|
||||
start_node = power_used and start_node or nil,
|
||||
stop_node = power_used and stop_node or nil,
|
||||
})
|
||||
|
||||
local tConsumer = {
|
||||
stage = stage,
|
||||
State = tState,
|
||||
-- number of items to be processed per cycle
|
||||
num_items = tNode.num_items and tNode.num_items[stage],
|
||||
power_consumption = power_used and
|
||||
tNode.power_consumption[stage] or 0,
|
||||
node_timer = tNode.node_timer,
|
||||
cycle_time = tNode.cycle_time,
|
||||
call_cycle = tNode.cycle_time / 2,
|
||||
power_netw = power_network,
|
||||
}
|
||||
|
||||
local after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local crd = CRD(pos)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
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", "")
|
||||
end
|
||||
local number = techage.add_node(pos, name_pas, stage == 2)
|
||||
if crd.power_netw then
|
||||
crd.power_netw:after_place_node(pos)
|
||||
end
|
||||
if tNode.after_place_node then
|
||||
tNode.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
end
|
||||
crd.State:node_init(pos, nvm, number)
|
||||
end
|
||||
|
||||
local after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
if tNode.after_dig_node then
|
||||
tNode.after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
end
|
||||
local crd = CRDN(oldnode)
|
||||
if crd.power_netw then
|
||||
crd.power_netw:after_dig_node(pos)
|
||||
end
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
tNode.groups.not_in_creative_inventory = 0
|
||||
|
||||
local def_pas = {
|
||||
description = name_inv,
|
||||
tiles = prepare_tiles(tiles.pas, stage, power_png),
|
||||
consumer = tConsumer,
|
||||
drawtype = tNode.drawtype,
|
||||
node_box = tNode.node_box,
|
||||
selection_box = tNode.selection_box,
|
||||
|
||||
can_dig = tNode.can_dig,
|
||||
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
||||
on_timer = node_timer_pas,
|
||||
on_receive_fields = tNode.on_receive_fields,
|
||||
on_rightclick = tNode.on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
preserve_metadata = tNode.preserve_metadata,
|
||||
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
||||
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
||||
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
||||
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
||||
ta_rotate_node = tNode.ta_rotate_node,
|
||||
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
||||
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
||||
|
||||
paramtype = tNode.paramtype,
|
||||
paramtype2 = "facedir",
|
||||
drop = tNode.drop,
|
||||
groups = table.copy(tNode.groups),
|
||||
is_ground_content = false,
|
||||
sounds = tNode.sounds,
|
||||
}
|
||||
|
||||
-- Copy custom properties (starting with an underscore)
|
||||
for k,v in pairs(tNode) do
|
||||
if string.sub(k, 1, 1) == "_" then
|
||||
def_pas[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node(name_pas, def_pas)
|
||||
|
||||
tNode.groups.not_in_creative_inventory = 1
|
||||
|
||||
local def_act = {
|
||||
description = name_inv,
|
||||
tiles = prepare_tiles(tiles.act, stage, power_png),
|
||||
consumer = tConsumer,
|
||||
drawtype = tNode.drawtype,
|
||||
node_box = tNode.node_box,
|
||||
selection_box = tNode.selection_box,
|
||||
|
||||
on_rotate = tNode.on_rotate or screwdriver.disallow,
|
||||
on_timer = node_timer_act,
|
||||
on_receive_fields = tNode.on_receive_fields,
|
||||
on_rightclick = tNode.on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
|
||||
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
|
||||
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
|
||||
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
|
||||
ta_rotate_node = tNode.ta_rotate_node,
|
||||
ta3_formspec = stage == 3 and tNode.ta3_formspec,
|
||||
ta4_formspec = stage == 4 and tNode.ta4_formspec,
|
||||
|
||||
paramtype = tNode.paramtype,
|
||||
paramtype2 = "facedir",
|
||||
drop = "",
|
||||
diggable = false,
|
||||
groups = table.copy(tNode.groups),
|
||||
is_ground_content = false,
|
||||
sounds = tNode.sounds,
|
||||
}
|
||||
|
||||
-- Copy custom properties (starting with an underscore)
|
||||
for k,v in pairs(tNode) do
|
||||
if string.sub(k, 1, 1) == "_" then
|
||||
def_act[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node(name_act, def_act)
|
||||
|
||||
if power_used then
|
||||
power.register_nodes({name_pas, name_act}, power_network, "con", sides)
|
||||
end
|
||||
techage.register_node({name_pas, name_act}, tNode.tubing)
|
||||
|
||||
if tNode.tube_sides then
|
||||
Tube:set_valid_sides(name_pas, get_keys(tNode.tube_sides))
|
||||
Tube:set_valid_sides(name_act, get_keys(tNode.tube_sides))
|
||||
end
|
||||
end
|
||||
end
|
||||
return names[1], names[2], names[3], names[4]
|
||||
end
|
@ -1,683 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Distributor
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local N = minetest.get_node
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local Tube = techage.Tube
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local SRC_INV_SIZE = 8
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
local FILTER_ITEM_LIMIT_PER_STACK = 12
|
||||
local FILTER_ITEM_LIMIT = 36
|
||||
|
||||
local INFO = [[Turn port on/off or read its state: command = 'port', payload = red/green/blue/yellow{=on/off}]]
|
||||
|
||||
|
||||
--local Side2Color = {B="red", L="green", F="blue", R="yellow"}
|
||||
local SlotColors = {"red", "green", "blue", "yellow"}
|
||||
local SlotNumbers = {red = 1, green = 2, blue = 3, yellow = 4}
|
||||
local Num2Ascii = {"B", "L", "F", "R"}
|
||||
local FilterCache = {} -- local cache for filter settings
|
||||
|
||||
local function filter_settings(pos)
|
||||
local meta = M(pos)
|
||||
local param2 = techage.get_node_lvm(pos).param2
|
||||
local inv = meta:get_inventory()
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
local ItemFilter = {} -- {<item:name> = {dir,...}]
|
||||
local OpenPorts = {} -- {dir, ...}
|
||||
local counter = 0 -- counts total item number in filter configuration
|
||||
|
||||
-- collect all filter settings
|
||||
for idx,slot in ipairs(SlotColors) do
|
||||
if filter[idx] == true then
|
||||
local side = Num2Ascii[idx]
|
||||
local out_dir = techage.side_to_outdir(side, param2)
|
||||
if inv:is_empty(slot) then
|
||||
table.insert(OpenPorts, out_dir)
|
||||
else
|
||||
for idx2,stack in ipairs(inv:get_list(slot)) do
|
||||
local name = stack:get_name()
|
||||
if name ~= "" then
|
||||
if not ItemFilter[name] then
|
||||
ItemFilter[name] = {}
|
||||
end
|
||||
for _ = 1, math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count()) do
|
||||
if counter > FILTER_ITEM_LIMIT then
|
||||
break
|
||||
end
|
||||
table.insert(ItemFilter[name], out_dir)
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FilterCache[minetest.hash_node_position(pos)] = {
|
||||
ItemFilter = ItemFilter,
|
||||
OpenPorts = OpenPorts,
|
||||
}
|
||||
end
|
||||
|
||||
-- Return filter table and list of open ports.
|
||||
-- (see test data)
|
||||
local function get_filter_settings(pos)
|
||||
-- local ItemFilter = {
|
||||
-- ["default:dirt"] = {1,2},
|
||||
-- ["default:cobble"] = {4},
|
||||
-- }
|
||||
-- local OpenPorts = {3}
|
||||
-- return ItemFilter, OpenPorts
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
if FilterCache[hash] == nil then
|
||||
filter_settings(pos)
|
||||
end
|
||||
return FilterCache[hash].ItemFilter, FilterCache[hash].OpenPorts
|
||||
end
|
||||
|
||||
local function blocking_checkbox(pos, filter, is_hp)
|
||||
local cnt = 0
|
||||
local _, open_ports = get_filter_settings(pos)
|
||||
local fs_pos = is_hp and "0.25,5" or "3,3.9"
|
||||
for _,val in ipairs(filter) do
|
||||
if val then cnt = cnt + 1 end
|
||||
end
|
||||
if cnt > 1 and #open_ports > 0 then
|
||||
local blocking = M(pos):get_int("blocking") == 1 and "true" or "false"
|
||||
return "checkbox["..fs_pos..";blocking;"..S("blocking mode")..";"..blocking.."]"..
|
||||
"tooltip["..fs_pos..";1,1;"..S("Block configured items for open ports")..";#0C3D32;#FFFFFF]"
|
||||
else
|
||||
M(pos):set_int("blocking", 0) -- disable blocking
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
|
||||
local is_hp = nvm.high_performance == true
|
||||
local blocking = blocking_checkbox(pos, filter, is_hp)
|
||||
|
||||
if is_hp then
|
||||
return "size[10.5,9.5]"..
|
||||
"box[0.25,-0.1;9.6,1.1;#005500]"..
|
||||
"label[0.6,0.2;"..S("Input").."]"..
|
||||
"list[context;src;1.75,0;8,1;]"..
|
||||
blocking..
|
||||
"image_button[0.25,5.8;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[0.25,5.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[0.25,1.2;filter1;On;"..dump(filter[1]).."]"..
|
||||
"checkbox[0.25,2.2;filter2;On;"..dump(filter[2]).."]"..
|
||||
"checkbox[0.25,3.2;filter3;On;"..dump(filter[3]).."]"..
|
||||
"checkbox[0.25,4.2;filter4;On;"..dump(filter[4]).."]"..
|
||||
"image[1.25,1.2;0.3,1;techage_inv_red.png]"..
|
||||
"image[1.25,2.2;0.3,1;techage_inv_green.png]"..
|
||||
"image[1.25,3.2;0.3,1;techage_inv_blue.png]"..
|
||||
"image[1.25,4.2;0.3,1;techage_inv_yellow.png]"..
|
||||
"list[context;red;1.75,1.2;8,1;]"..
|
||||
"list[context;green;1.75,2.2;8,1;]"..
|
||||
"list[context;blue;1.75,3.2;8,1;]"..
|
||||
"list[context;yellow;1.75,4.2;8,1;]"..
|
||||
"list[current_player;main;1.75,5.8;8,4;]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(1.75,5.8)
|
||||
else
|
||||
return "size[10.5,8.5]"..
|
||||
"list[context;src;0,0;2,4;]"..
|
||||
blocking..
|
||||
"image[2,1.5;1,1;techage_form_arrow.png]"..
|
||||
"image_button[0,4.8;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[0,4.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[3,0;filter1;On;"..dump(filter[1]).."]"..
|
||||
"checkbox[3,1;filter2;On;"..dump(filter[2]).."]"..
|
||||
"checkbox[3,2;filter3;On;"..dump(filter[3]).."]"..
|
||||
"checkbox[3,3;filter4;On;"..dump(filter[4]).."]"..
|
||||
"image[4,0;0.3,1;techage_inv_red.png]"..
|
||||
"image[4,1;0.3,1;techage_inv_green.png]"..
|
||||
"image[4,2;0.3,1;techage_inv_blue.png]"..
|
||||
"image[4,3;0.3,1;techage_inv_yellow.png]"..
|
||||
"list[context;red;4.5,0;6,1;]"..
|
||||
"list[context;green;4.5,1;6,1;]"..
|
||||
"list[context;blue;4.5,2;6,1;]"..
|
||||
"list[context;yellow;4.5,3;6,1;]"..
|
||||
"list[current_player;main;1.25,4.8;8,4;]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(1.25,4.8)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_total_filter_items_number(pos, except_listname, except_index)
|
||||
local inv = M(pos):get_inventory()
|
||||
local total = 0
|
||||
for _, listname in ipairs(SlotColors) do
|
||||
local list = inv:get_list(listname)
|
||||
for idx, stack in ipairs(list) do
|
||||
if not (listname == except_listname and idx == except_index) then
|
||||
total = total + stack:get_count()
|
||||
end
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
else
|
||||
stack:add_item(list[index])
|
||||
local max_items_to_limit = FILTER_ITEM_LIMIT - get_total_filter_items_number(pos, listname, index)
|
||||
stack:set_count(math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count(), max_items_to_limit))
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
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
|
||||
if listname == "src" then
|
||||
return stack:get_count()
|
||||
else
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
list[index]:take_item(stack:get_count())
|
||||
inv:set_stack(listname, index, list[index])
|
||||
return 0
|
||||
end
|
||||
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 = minetest.get_meta(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
|
||||
if from_list == "src" and to_list ~= "src" then
|
||||
stack:add_item(inv:get_stack(to_list, to_index))
|
||||
local max_items_to_limit = FILTER_ITEM_LIMIT - get_total_filter_items_number(pos, to_list, to_index)
|
||||
stack:set_count(math.min(FILTER_ITEM_LIMIT_PER_STACK, stack:get_count(), max_items_to_limit))
|
||||
inv:set_stack(to_list, to_index, stack)
|
||||
return 0
|
||||
elseif from_list ~= "src" and to_list == "src" then
|
||||
inv:set_stack(from_list, from_index, nil)
|
||||
return 0
|
||||
elseif from_list ~= "src" and to_list ~= "src" then
|
||||
return math.min(stack:get_count(), FILTER_ITEM_LIMIT_PER_STACK - inv:get_stack(to_list, to_index):get_count())
|
||||
else
|
||||
return stack:get_count()
|
||||
end
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local is_ta4_tube = true
|
||||
for dir = 1,4 do
|
||||
for i, pos, node in Tube:get_tube_line(pos, dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
if CRD(pos).stage == 4 and not is_ta4_tube then
|
||||
nvm.num_items = crd.num_items / 2
|
||||
else
|
||||
nvm.num_items = crd.num_items
|
||||
end
|
||||
end
|
||||
|
||||
local function shuffle(list)
|
||||
for i = #list, 2, -1 do
|
||||
local j = math.random(i)
|
||||
list[i], list[j] = list[j], list[i]
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local function push_item(pos, base_filter, itemstack, num_items, nvm)
|
||||
local filter = shuffle(table.copy(base_filter))
|
||||
local idx = 1
|
||||
local num_pushed = 0
|
||||
local num_ports = #filter
|
||||
local amount = math.floor(math.max((num_items + 1) / num_ports, 1))
|
||||
local num_of_trials = 0
|
||||
while num_pushed < num_items and num_of_trials <= 8 do
|
||||
num_of_trials = num_of_trials + 1
|
||||
local push_dir = filter[idx]
|
||||
local num_to_push = math.min(amount, num_items - num_pushed)
|
||||
local leftover = techage.push_items(pos, push_dir, itemstack:peek_item(num_to_push))
|
||||
local pushed
|
||||
if not leftover then
|
||||
pushed = 0
|
||||
elseif leftover ~= true then
|
||||
pushed = num_to_push - leftover:get_count()
|
||||
else -- leftover == true
|
||||
pushed = num_to_push
|
||||
end
|
||||
num_pushed = num_pushed + pushed
|
||||
nvm.port_counter[push_dir] = (nvm.port_counter[push_dir] or 0) + pushed
|
||||
-- filter start offset
|
||||
idx = idx + 1
|
||||
if idx > num_ports then
|
||||
idx = 1
|
||||
end
|
||||
end
|
||||
return num_pushed
|
||||
end
|
||||
|
||||
-- move items to output slots
|
||||
local function distributing(pos, inv, crd, nvm)
|
||||
local item_filter, open_ports = get_filter_settings(pos)
|
||||
local sum_num_pushed = 0
|
||||
local num_pushed = 0
|
||||
local blocking_mode = M(pos):get_int("blocking") == 1
|
||||
|
||||
-- start searching after last position
|
||||
local offs = nvm.last_index or 1
|
||||
|
||||
for i = 1, SRC_INV_SIZE do
|
||||
local idx = ((i + offs - 1) % 8) + 1
|
||||
local stack = inv:get_stack("src", idx)
|
||||
local item_name = stack:get_name()
|
||||
local num_items = stack:get_count()
|
||||
local num_to_push = math.min((nvm.num_items or crd.num_items) - sum_num_pushed, num_items)
|
||||
local stack_to_push = stack:peek_item(num_to_push)
|
||||
local filter = item_filter[item_name]
|
||||
num_pushed = 0
|
||||
|
||||
if filter and #filter > 0 then
|
||||
-- Push items based on filter
|
||||
num_pushed = push_item(pos, filter, stack_to_push, num_to_push, nvm)
|
||||
elseif blocking_mode and #open_ports > 0 then
|
||||
-- Push items based on open ports
|
||||
num_pushed = push_item(pos, open_ports, stack_to_push, num_to_push, nvm)
|
||||
end
|
||||
if not blocking_mode and num_pushed == 0 and #open_ports > 0 then
|
||||
-- Push items based on open ports
|
||||
num_pushed = push_item(pos, open_ports, stack_to_push, num_to_push, nvm)
|
||||
end
|
||||
|
||||
sum_num_pushed = sum_num_pushed + num_pushed
|
||||
stack:take_item(num_pushed)
|
||||
inv:set_stack("src", idx, stack)
|
||||
if sum_num_pushed >= (nvm.num_items or crd.num_items) then
|
||||
nvm.last_index = idx
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if sum_num_pushed == 0 then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
|
||||
-- move items to the output slots
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.port_counter = nvm.port_counter or {}
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if not inv:is_empty("src") then
|
||||
distributing(pos, inv, crd, nvm)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
return crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local meta = M(pos)
|
||||
local crd = CRD(pos)
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
if fields.filter1 ~= nil then
|
||||
filter[1] = fields.filter1 == "true"
|
||||
elseif fields.filter2 ~= nil then
|
||||
filter[2] = fields.filter2 == "true"
|
||||
elseif fields.filter3 ~= nil then
|
||||
filter[3] = fields.filter3 == "true"
|
||||
elseif fields.filter4 ~= nil then
|
||||
filter[4] = fields.filter4 == "true"
|
||||
elseif fields.blocking ~= nil then
|
||||
meta:set_int("blocking", fields.blocking == "true" and 1 or 0)
|
||||
end
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
|
||||
filter_settings(pos)
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if fields.state_button ~= nil then
|
||||
crd.State:state_button_event(pos, nvm, fields)
|
||||
else
|
||||
meta:set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
-- techage command to turn on/off filter channels
|
||||
local function change_filter_settings(pos, slot, val)
|
||||
local meta = M(pos)
|
||||
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
|
||||
local num = SlotNumbers[slot] or 1
|
||||
if num >= 1 and num <= 4 then
|
||||
filter[num] = val == "on"
|
||||
end
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
meta:set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
return true
|
||||
end
|
||||
|
||||
-- techage command to read filter channel status (on/off)
|
||||
local function read_filter_settings(pos, slot)
|
||||
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
|
||||
return filter[SlotNumbers[slot]] and "on" or "off"
|
||||
end
|
||||
|
||||
local function get_payload_values(payload)
|
||||
local color
|
||||
local idx = 0
|
||||
local items = {ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack(""), ItemStack("")}
|
||||
for s in payload:gmatch("[^%s]+") do --- white spaces
|
||||
if not color then
|
||||
if SlotNumbers[s] then
|
||||
color = s
|
||||
else
|
||||
return "red", {}
|
||||
end
|
||||
else
|
||||
idx = idx + 1
|
||||
if idx <= 6 then
|
||||
items[idx] = ItemStack(s)
|
||||
end
|
||||
end
|
||||
end
|
||||
return color, items
|
||||
end
|
||||
|
||||
local function str_of_inv_items(pos, color)
|
||||
color = SlotColors[color] or color
|
||||
if SlotNumbers[color] then
|
||||
local inv = M(pos):get_inventory()
|
||||
local t = {}
|
||||
for idx = 1, 6 do
|
||||
local item = inv:get_stack(color, idx)
|
||||
if item:get_count() > 0 then
|
||||
t[#t + 1] = item:get_name()
|
||||
end
|
||||
end
|
||||
return table.concat(t, " ")
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("src")
|
||||
end
|
||||
|
||||
local get_tiles = function(is_hp)
|
||||
local variant = is_hp and "_hp" or ""
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_appl_distri.png^techage_frame_ta#_top"..variant..".png^techage_appl_color_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top"..variant..".png^(techage_appl_color_top.png^[transformFY)",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_yellow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_green.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_red.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_blue.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_distri4.png^techage_frame4_ta#_top"..variant..".png^techage_appl_color_top4.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top"..variant..".png^(techage_appl_color_top.png^[transformFY)",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_yellow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_green.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_red.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#"..variant..".png^techage_appl_distri_blue.png",
|
||||
}
|
||||
return tiles
|
||||
end
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "src", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "info" then
|
||||
return INFO
|
||||
elseif topic == "port" then
|
||||
-- "red"/"green"/"blue"/"yellow" = "on"/"off"
|
||||
local slot, val = techage.ident_value(payload)
|
||||
if val == "" then
|
||||
return read_filter_settings(pos, slot)
|
||||
else
|
||||
return change_filter_settings(pos, slot, val)
|
||||
end
|
||||
elseif topic == "config" then
|
||||
local color, items = get_payload_values(payload)
|
||||
local inv = M(pos):get_inventory()
|
||||
for idx,item in ipairs(items) do
|
||||
inv:set_stack(color, idx, item)
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
return true
|
||||
elseif topic == "get" then
|
||||
return str_of_inv_items(pos, payload)
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 4 then
|
||||
local slot = SlotColors[payload[1]]
|
||||
local state = payload[2] == 1 and "on" or "off"
|
||||
change_filter_settings(pos, slot, state)
|
||||
return 0
|
||||
elseif topic == 67 then
|
||||
local color, items = get_payload_values(payload)
|
||||
local inv = M(pos):get_inventory()
|
||||
for idx,item in ipairs(items) do
|
||||
inv:set_stack(color, idx, item)
|
||||
end
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
FilterCache[hash] = nil
|
||||
return 0
|
||||
else
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 148 then
|
||||
return 0, str_of_inv_items(pos, payload[1])
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local def = {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local filter = {false,false,false,false}
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('src', 8)
|
||||
inv:set_size('yellow', 6)
|
||||
inv:set_size('green', 6)
|
||||
inv:set_size('red', 6)
|
||||
inv:set_size('blue', 6)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list)
|
||||
if from_list ~= "src" or to_list ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname)
|
||||
if listname ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
on_metadata_inventory_take = function(pos, listname)
|
||||
if listname ~= "src" then
|
||||
filter_settings(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,4,12,24},
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 = techage.register_consumer(
|
||||
"distributor",
|
||||
S("Distributor"),
|
||||
get_tiles(false),
|
||||
def
|
||||
)
|
||||
|
||||
local hp_def = table.copy(def)
|
||||
|
||||
hp_def.after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.high_performance = true
|
||||
local filter = {false,false,false,false}
|
||||
meta:set_string("filter", minetest.serialize(filter))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('src', 8)
|
||||
inv:set_size('yellow', 8)
|
||||
inv:set_size('green', 8)
|
||||
inv:set_size('red', 8)
|
||||
inv:set_size('blue', 8)
|
||||
end
|
||||
hp_def.num_items = {0,0,0,36}
|
||||
|
||||
local _, _, node_name_ta4_hp = techage.register_consumer(
|
||||
"high_performance_distributor", S("High Performance Distributor"),
|
||||
get_tiles(true),
|
||||
hp_def,
|
||||
{false, false, false, true}
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2.." 2",
|
||||
recipe = {
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
{"techage:tubeS", "default:mese_crystal", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4_hp,
|
||||
recipe = {
|
||||
{node_name_ta4, "default:copper_ingot"},
|
||||
{"default:mese_crystal_fragment", node_name_ta4},
|
||||
},
|
||||
})
|
@ -1,314 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Electronic Fab
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 6
|
||||
|
||||
local recipes = techage.recipes
|
||||
|
||||
local RecipeType = {
|
||||
[2] = "ta2_electronic_fab",
|
||||
[3] = "ta3_electronic_fab",
|
||||
[4] = "ta4_electronic_fab",
|
||||
}
|
||||
|
||||
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]"..
|
||||
"list[context;src;0,0;2,4;]"..
|
||||
recipes.formspec(2.2, 0, rtype, nvm, owner)..
|
||||
"list[context;dst;6.4,0;2,4;]"..
|
||||
"image_button[3.7,3.3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.7,3.3;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0.2,4.5;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0.2, 4.5)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
local crd = CRD(pos)
|
||||
if listname == "src" then
|
||||
crd.State:start_if_standby(pos)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function get_original_waste(inv, waste)
|
||||
-- Waste has meta data, so we need to find the original waste item
|
||||
for i = 1, 8 do
|
||||
local stack = inv:get_stack("src", i)
|
||||
if stack:get_count() == 1 then
|
||||
if stack:get_name() == waste:get_name() then
|
||||
return stack
|
||||
end
|
||||
end
|
||||
end
|
||||
return waste
|
||||
end
|
||||
|
||||
local function making(pos, crd, nvm, inv)
|
||||
local owner = M(pos):get_string("owner")
|
||||
local rtype = RecipeType[crd.stage]
|
||||
local recipe = recipes.get(nvm, rtype, owner)
|
||||
local output = ItemStack(recipe.output.name .. " " .. recipe.output.num)
|
||||
local waste = recipe.waste and ItemStack(recipe.waste.name .. " " .. recipe.waste.num)
|
||||
if inv:room_for_item("dst", output) and (not waste or inv:room_for_item("dst", waste)) then
|
||||
for _,item in ipairs(recipe.input) do
|
||||
local input = ItemStack(item.name.." "..item.num)
|
||||
if not inv:contains_item("src", input) then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- For some recipes, an item customized via metadata is used as a copy template.
|
||||
-- This allows specially programmed items such as ROM chips to be produced.
|
||||
-- The metadata of the copy template must be passed to the on_production function.
|
||||
-- At the same time, the metadata of the copy template must not be lost when moving
|
||||
-- as 'waste' to the output inventory.
|
||||
local idef = minetest.registered_items[recipe.output.name]
|
||||
if waste and idef and idef.on_production then
|
||||
waste = get_original_waste(inv, waste)
|
||||
local metadata = waste:get_meta():to_table().fields or {}
|
||||
output = idef.on_production(output, metadata)
|
||||
end
|
||||
for _,item in ipairs(recipe.input) do
|
||||
local input = ItemStack(item.name.." "..item.num)
|
||||
inv:remove_item("src", input)
|
||||
end
|
||||
inv:add_item("dst", output)
|
||||
if waste then
|
||||
inv:add_item("dst", waste)
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
if inv then
|
||||
making(pos, crd, nvm, inv)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
|
||||
if not nvm.running then
|
||||
recipes.on_receive_fields(pos, formname, fields, player)
|
||||
end
|
||||
|
||||
crd.State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_electronic_fab.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_electronic_fab.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_electronic_fab4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_appl_electronic_fab4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
if access_type == "push" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
return meta:get_inventory(), "src"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack, idx)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack, idx)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("electronic_fab", S("Electronic Fab"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 8)
|
||||
inv:set_size("dst", 8)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,8,12,12},
|
||||
},
|
||||
{false, true, true, true}) -- TA2/TA3/TA4
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:diamond", "group:wood"},
|
||||
{"techage:tubeS", "basic_materials:gear_steel", "techage:tubeS"},
|
||||
{"group:wood", "default:steel_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:diamond", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("ta2_electronic_fab", {
|
||||
description = S("TA2 Ele Fab"),
|
||||
icon = 'techage_filling_ta2.png^techage_appl_electronic_fab.png^techage_frame_ta2.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta3_electronic_fab", {
|
||||
description = S("TA3 Ele Fab"),
|
||||
icon = 'techage_filling_ta3.png^techage_appl_electronic_fab.png^techage_frame_ta3.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta4_electronic_fab", {
|
||||
description = S("TA4 Ele Fab"),
|
||||
icon = 'techage_filling_ta4.png^techage_appl_electronic_fab.png^techage_frame_ta4.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
@ -1,340 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Forceload block
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S = techage.S
|
||||
|
||||
local function calc_area(pos)
|
||||
local xpos = (math.floor(pos.x / 16) * 16)
|
||||
local ypos = (math.floor(pos.y / 16) * 16)
|
||||
local zpos = (math.floor(pos.z / 16) * 16)
|
||||
local pos1 = {x=xpos, y=ypos, z=zpos}
|
||||
local pos2 = {x=xpos+15, y=ypos+15, z=zpos+15}
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
local function in_list(list, x)
|
||||
local pos1 = calc_area(x)
|
||||
for _,v in ipairs(list) do
|
||||
local pos2 = calc_area(v)
|
||||
if vector.equals(pos1, pos2) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function remove_list_elem(list, x)
|
||||
local n = nil
|
||||
for idx, v in ipairs(list) do
|
||||
if vector.equals(v, x) then
|
||||
n = idx
|
||||
break
|
||||
end
|
||||
end
|
||||
if n then
|
||||
table.remove(list, n)
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local function chat(player, text)
|
||||
minetest.chat_send_player(player:get_player_name(), "[Techage] "..text)
|
||||
end
|
||||
|
||||
local function postload_area(pos)
|
||||
minetest.log("warning", "[FLB] area "..P2S(pos).." not loaded!")
|
||||
if not minetest.forceload_block(pos, true) then
|
||||
minetest.after(60, postload_area, pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function add_pos(pos, player)
|
||||
local meta = player:get_meta()
|
||||
local lPos = minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
if not in_list(lPos, pos) and (#lPos < techage.max_num_forceload_blocks or
|
||||
minetest.global_exists("creative") and creative.is_enabled_for and
|
||||
creative.is_enabled_for(player:get_player_name())) then
|
||||
lPos[#lPos+1] = pos
|
||||
local meta = player:get_meta()
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function del_pos(pos, player)
|
||||
local meta = player:get_meta()
|
||||
local lPos = minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
lPos = remove_list_elem(lPos, pos)
|
||||
if next(lPos) then
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
else
|
||||
meta:set_string("techage_forceload_blocks", "")
|
||||
end
|
||||
end
|
||||
|
||||
local function get_pos_list(player)
|
||||
local meta = player:get_meta()
|
||||
return minetest.deserialize(meta:get_string("techage_forceload_blocks")) or {}
|
||||
end
|
||||
|
||||
local function set_pos_list(player, lPos)
|
||||
local meta = player:get_meta()
|
||||
if next(lPos) then
|
||||
meta:set_string("techage_forceload_blocks", minetest.serialize(lPos))
|
||||
else
|
||||
meta:set_string("techage_forceload_blocks", "")
|
||||
end
|
||||
end
|
||||
|
||||
local function show_flbs(pos, name, range)
|
||||
local pos1 = {x=pos.x-range, y=pos.y-range, z=pos.z-range}
|
||||
local pos2 = {x=pos.x+range, y=pos.y+range, z=pos.z+range}
|
||||
for _,npos in ipairs(minetest.find_nodes_in_area(pos1, pos2, {"techage:forceload", "techage:forceloadtile"})) do
|
||||
local _pos1, _pos2 = calc_area(npos)
|
||||
local owner = M(npos):get_string("owner")
|
||||
techage.mark_region(name, _pos1, _pos2, owner .. " " .. P2S(npos))
|
||||
end
|
||||
end
|
||||
|
||||
local function get_data(pos, player)
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
local meta = player:get_meta()
|
||||
local num = #minetest.deserialize(meta:get_string("techage_forceload_blocks")) or 0
|
||||
local max = techage.max_num_forceload_blocks
|
||||
return pos1, pos2, num, max
|
||||
end
|
||||
|
||||
local function formspec(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local lPos = get_pos_list(player)
|
||||
local tRes = {}
|
||||
tRes[#tRes+1] = "#"
|
||||
tRes[#tRes+1] = S("Block at pos")
|
||||
tRes[#tRes+1] = S("Area from")
|
||||
tRes[#tRes+1] = S("Area to")
|
||||
tRes[#tRes+1] = S("Status")
|
||||
for idx,pos in ipairs(lPos) do
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
tRes[#tRes+1] = idx
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos))
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos1))
|
||||
tRes[#tRes+1] = minetest.formspec_escape(P2S(pos2))
|
||||
tRes[#tRes+1] = minetest.forceload_block(pos, true) and 'Loaded' or 'Unloaded'
|
||||
end
|
||||
return "size[9,9]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"label[0,0;"..S("List of your Forceload Blocks:").."]"..
|
||||
"tablecolumns[text,width=1.8;text,width=12;text,width=12;text,width=12;text,width=12]"..
|
||||
"table[0,0.6;8.8,8.4;output;"..table.concat(tRes, ",")..";1]"
|
||||
end
|
||||
end
|
||||
|
||||
local function on_place(itemstack, placer, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
return minetest.rotate_and_place(itemstack, placer, pointed_thing)
|
||||
end
|
||||
|
||||
local function after_place_node(pos, placer, itemstack)
|
||||
if add_pos(pos, placer) then
|
||||
minetest.forceload_block(pos, true)
|
||||
local pos1, pos2, num, max = get_data(pos, placer)
|
||||
M(pos):set_string("infotext", "Area "..P2S(pos1).." to "..P2S(pos2).." "..S("loaded").."!\n"..
|
||||
S("Punch the block to make the area visible."))
|
||||
chat(placer, "Area ("..num.."/"..max..") "..P2S(pos1).." to "..P2S(pos2).." "..S("loaded").."!")
|
||||
techage.mark_region(placer:get_player_name(), pos1, pos2)
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
else
|
||||
chat(placer, S("Area already loaded or max. number of Forceload Blocks reached!"))
|
||||
minetest.remove_node(pos)
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
local player = minetest.get_player_by_name(oldmetadata.fields.owner)
|
||||
if player then
|
||||
del_pos(pos, player)
|
||||
end
|
||||
minetest.forceload_free_block(pos, true)
|
||||
techage.unmark_region(oldmetadata.fields.owner)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
|
||||
local owner = M(pos):get_string("owner")
|
||||
local name = clicker:get_player_name()
|
||||
if name == owner or minetest.check_player_privs(name, "server") then
|
||||
local s = formspec(owner)
|
||||
if s then
|
||||
minetest.show_formspec(name, "techage:forceload", s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_punch(pos, node, puncher, pointed_thing)
|
||||
local pos1, pos2 = calc_area(pos)
|
||||
techage.switch_region(puncher:get_player_name(), pos1, pos2)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:forceload", {
|
||||
description = S("Techage Forceload Block"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
'techage_filling_ta2.png^techage_frame_ta2_top.png',
|
||||
'techage_filling_ta2.png^techage_frame_ta2_top.png',
|
||||
{
|
||||
name = "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_forceload.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
on_rightclick = on_rightclick,
|
||||
on_punch = on_punch,
|
||||
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
use_texture_alpha = techage.CLIP,
|
||||
groups = {choppy=2, cracky=2, crumbly=2,
|
||||
digtron_protected = 1,
|
||||
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:forceloadtile", {
|
||||
description = S("Techage Forceload Tile"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_forceload.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
--{-5/16, -7/16, -5/16, 5/16, -5/16, 5/16},
|
||||
{-4/16, -8/16, -4/16, 4/16, -15/32, 4/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_place = on_place,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
on_rightclick = on_rightclick,
|
||||
on_punch = on_punch,
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
sunlight_propagates = true,
|
||||
groups = {choppy=2, cracky=2, crumbly=2,
|
||||
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
if techage.max_num_forceload_blocks > 0 then
|
||||
minetest.register_craft({
|
||||
output = "techage:forceload",
|
||||
recipe = {
|
||||
{"group:wood", "", "group:wood"},
|
||||
{"default:mese_crystal_fragment", "techage:usmium_nuggets", "default:mese_crystal_fragment"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:forceloadtile",
|
||||
recipe = {"techage:forceload"},
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:forceload",
|
||||
recipe = {"techage:forceloadtile"},
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local lPos = {}
|
||||
for _,pos in ipairs(get_pos_list(player)) do
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == "techage:forceload" or node.name == "techage:forceloadtile" then
|
||||
if not minetest.forceload_block(pos, true) then
|
||||
minetest.after(60, postload_area, pos)
|
||||
end
|
||||
lPos[#lPos+1] = pos
|
||||
end
|
||||
end
|
||||
set_pos_list(player, lPos)
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
for _,pos in ipairs(get_pos_list(player)) do
|
||||
minetest.forceload_free_block(pos, true)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_chatcommand("forceload", {
|
||||
params = "",
|
||||
description = S("Show all forceload blocks in a 64x64x64 range"),
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local pos = player:get_pos()
|
||||
pos = vector.round(pos)
|
||||
show_flbs(pos, name, 64)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("forceload_verify", {
|
||||
params = "",
|
||||
description = "Checks each forceload block and returns a count of active/placed blocks",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local loaded = {}
|
||||
local wanted = get_pos_list(player)
|
||||
for _,pos in ipairs(wanted) do
|
||||
if minetest.forceload_block(pos, true) then
|
||||
loaded[#loaded+1] = pos
|
||||
end
|
||||
end
|
||||
minetest.chat_send_player(name, "Found "..#loaded.." out of ".. #wanted .. " force loads")
|
||||
end
|
||||
end,
|
||||
})
|
@ -1,159 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube support for default chests and furnace
|
||||
|
||||
]]--
|
||||
|
||||
local OwnerCache = {
|
||||
}
|
||||
|
||||
-- Check if the chest is in the protected area of the owner
|
||||
local function is_owner(pos, meta)
|
||||
local owner = meta:get_string("owner")
|
||||
local key = minetest.hash_node_position(pos)
|
||||
-- If successfull, store info in cache
|
||||
if OwnerCache[key] ~= owner then
|
||||
if not minetest.is_protected(pos, owner) then
|
||||
OwnerCache[key] = owner
|
||||
end
|
||||
end
|
||||
return OwnerCache[key] == owner
|
||||
end
|
||||
|
||||
|
||||
techage.register_node({"default:chest", "default:chest_open"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"default:chest_locked", "default:chest_locked_open"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
return meta:get_inventory(), "main"
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"shop:shop"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
if access_type == "push" then
|
||||
return meta:get_inventory(), "stock"
|
||||
elseif access_type == "pull" then
|
||||
return meta:get_inventory(), "register"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if is_owner(pos, meta) then
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "register", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "stock", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "register", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"default:furnace", "default:furnace_active"}, {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
minetest.get_node_timer(pos):start(1.0)
|
||||
if in_dir == 5 then
|
||||
return techage.put_items(inv, "src", stack)
|
||||
elseif minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
else
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"mobs:beehive"}, {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "beehive", num)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "beehive", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"xdecor:hive"}, {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "honey", num)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "honey", stack)
|
||||
end,
|
||||
})
|
@ -1,341 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2 Gravel Rinser, washing sieved gravel to find more ores
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local Probability = {}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:gravel]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
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
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
elseif listname == "dst" then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
|
||||
local function get_water_level(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if minetest.get_item_group(node.name, "water") > 0 then
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if ndef and ndef.liquidtype == "flowing" then
|
||||
return node.param2
|
||||
end
|
||||
end
|
||||
return 99
|
||||
end
|
||||
|
||||
local function determine_water_dir(pos)
|
||||
local lvl = get_water_level(pos)
|
||||
if lvl > get_water_level({x=pos.x+1, y=pos.y, z=pos.z}) then
|
||||
return 2
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x-1, y=pos.y, z=pos.z}) then
|
||||
return 4
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x, y=pos.y, z=pos.z+1}) then
|
||||
return 1
|
||||
end
|
||||
if lvl > get_water_level({x=pos.x, y=pos.y, z=pos.z-1}) then
|
||||
return 3
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function set_velocity(obj, pos, vel)
|
||||
if obj then
|
||||
obj:set_acceleration({x = 0, y = 0, z = 0})
|
||||
local p = obj:get_pos()
|
||||
if p then
|
||||
obj:set_pos({x=p.x, y=p.y-0.3, z=p.z})
|
||||
obj:set_velocity(vel)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function add_object(pos, name)
|
||||
local dir = determine_water_dir(pos)
|
||||
if dir > 0 then
|
||||
local obj = minetest.add_item(pos, ItemStack(name))
|
||||
local vel = vector.multiply(tubelib2.Dir6dToVector[dir], 0.3)
|
||||
minetest.after(0.3, set_velocity, obj, pos, vel)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_random_gravel_ore()
|
||||
for ore, probability in pairs(Probability) do
|
||||
if math.random(probability) == 1 then
|
||||
return ore
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function remove_objects(pos)
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local lua_entity = object:get_luaentity()
|
||||
if not object:is_player() and lua_entity and lua_entity.name == "__builtin:item" then
|
||||
object:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function washing(pos, crd, nvm, inv)
|
||||
-- for testing purposes
|
||||
if inv:contains_item("src", ItemStack("default:stick")) then
|
||||
add_object({x=pos.x, y=pos.y+1, z=pos.z}, "default:stick")
|
||||
inv:remove_item("src", ItemStack("default:stick"))
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
end
|
||||
|
||||
local src = ItemStack("techage:sieved_gravel")
|
||||
local dst = ItemStack("default:sand")
|
||||
if inv:contains_item("src", src) then
|
||||
if not inv:room_for_item("dst", dst) then
|
||||
crd.State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
local ore = get_random_gravel_ore()
|
||||
if ore then
|
||||
add_object({x=pos.x, y=pos.y+1, z=pos.z}, ore)
|
||||
end
|
||||
inv:add_item("dst", dst)
|
||||
inv:remove_item("src", src)
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
washing(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_rinser_top.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_rinser4_top.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_rinser.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
-- CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
remove_objects({x=pos.x, y=pos.y+1, z=pos.z})
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("rinser", S("Gravel Rinser"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -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},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
{-6/16, 6/16, -1/16, 6/16, 8/16, 1/16},
|
||||
{-1/16, 6/16, -6/16, 1/16, 8/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,3,3,3},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
},
|
||||
{false, true, true, false}) -- TA2/TA3
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:sieve", "techage:tubeS"},
|
||||
{"group:wood", "default:tin_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
techage.recipes.register_craft_type("rinsing", {
|
||||
description = S("Rinsing"),
|
||||
icon = "techage_appl_rinser_top.png^techage_frame_ta2_top.png",
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
|
||||
function techage.add_rinser_recipe(recipe)
|
||||
Probability[recipe.output] = recipe.probability
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "rinsing"
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
|
||||
techage.add_rinser_recipe({input="techage:sieved_gravel", output="techage:usmium_nuggets", probability=30})
|
||||
techage.add_rinser_recipe({input="techage:sieved_gravel", output="default:copper_lump", probability=15})
|
@ -1,287 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Gravel Sieve, sieving gravel to find ores
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local get_random_gravel_ore = techage.gravelsieve_get_random_gravel_ore
|
||||
local get_random_basalt_ore = techage.gravelsieve_get_random_basalt_ore
|
||||
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:gravel]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
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
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
return stack:get_count()
|
||||
elseif listname == "dst" then
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function sieving(pos, crd, nvm, inv)
|
||||
local src, dst
|
||||
for i = 1, crd.num_items do
|
||||
if inv:contains_item("src", ItemStack("techage:basalt_gravel")) then
|
||||
dst, src = get_random_basalt_ore(), ItemStack("techage:basalt_gravel")
|
||||
elseif inv:contains_item("src", ItemStack("default:gravel")) then
|
||||
dst, src = get_random_gravel_ore(), ItemStack("default:gravel")
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
if not inv:room_for_item("dst", dst) then
|
||||
crd.State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
inv:add_item("dst", dst)
|
||||
inv:remove_item("src", src)
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
sieving(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_sieve_top.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_sieve4_top.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_sieve.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("gravelsieve", S("Gravel Sieve"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -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},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 4/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,3,4,5},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:sieve", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("ta2_gravelsieve", {
|
||||
description = S("TA2 Gravel Sieve"),
|
||||
icon = 'techage_sieve_sieve_ta1.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta3_gravelsieve", {
|
||||
description = S("TA3 Gravel Sieve"),
|
||||
icon = 'techage_filling_ta3.png^techage_appl_sieve.png^techage_frame_ta3.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft_type("ta4_gravelsieve", {
|
||||
description = S("TA4 Gravel Sieve"),
|
||||
icon = 'techage_filling_ta4.png^techage_appl_sieve.png^techage_frame_ta4.png',
|
||||
width = 1,
|
||||
height = 1,
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta2_gravelsieve",
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta3_gravelsieve",
|
||||
})
|
||||
techage.recipes.register_craft({
|
||||
output = "techage:sieved_basalt_gravel",
|
||||
items = {"techage:basalt_gravel"},
|
||||
type = "ta4_gravelsieve",
|
||||
})
|
@ -1,435 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Grinder, grinding Cobble/Basalt to Gravel
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer or {} end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
-- Grinder recipes TA1
|
||||
local RecipesTa1 = {}
|
||||
-- Grinder recipes TA2 - TA4
|
||||
local Recipes = {}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
"item_image[0,0;1,1;default:cobble]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
"item_image[5,0;1,1;default:gravel]"..
|
||||
"image[5,0;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
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
|
||||
if listname == "src" then
|
||||
local state = CRD(pos).State
|
||||
if state then
|
||||
state:start_if_standby(pos)
|
||||
end
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
-- Grinder normaly handles 'num_items' per cycle. 'num_items' is node stage dependent.
|
||||
-- But if 'inp_num' > 1 (wheat recipes), use 'inp_num' and produce one output item.
|
||||
local function src_to_dst(src_stack, idx, src_name, num_items, inp_num, inv, dst_name)
|
||||
if inp_num > 1 then
|
||||
local input = ItemStack(src_name)
|
||||
input:set_count(inp_num)
|
||||
local output = ItemStack(dst_name)
|
||||
if inv:contains_item("src", input) and inv:room_for_item("dst", output) then
|
||||
inv:remove_item("src", input)
|
||||
inv:add_item("dst", output)
|
||||
return true
|
||||
end
|
||||
else
|
||||
local taken = src_stack:take_item(num_items)
|
||||
local output = ItemStack(dst_name)
|
||||
output:set_count(output:get_count() * taken:get_count())
|
||||
if inv:room_for_item("dst", output) then
|
||||
inv:set_stack("src", idx, src_stack)
|
||||
inv:add_item("dst", output)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function grinding(pos, crd, nvm, inv)
|
||||
local blocked = false -- idle
|
||||
for idx,stack in ipairs(inv:get_list("src")) do
|
||||
if not stack:is_empty() then
|
||||
local name = stack:get_name()
|
||||
if Recipes[name] then
|
||||
local recipe = Recipes[name]
|
||||
if src_to_dst(stack, idx, name, crd.num_items, recipe.inp_num, inv, recipe.output) then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
return
|
||||
else
|
||||
blocked = true
|
||||
end
|
||||
else
|
||||
crd.State:fault(pos, nvm)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
if blocked then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
grinding(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_grinder.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_grinder4.png^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_grinder2.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("grinder", S("Grinder"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -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},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,4,6,9},
|
||||
tube_sides = {L=1, R=1, U=1},
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- TA1 Mill (watermill)
|
||||
-------------------------------------------------------------------------------
|
||||
local formspecStr = "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;1,1;1,1;]"..
|
||||
"item_image[1,1;1,1;farming:wheat]"..
|
||||
"image[1,1;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"list[context;dst;6,1;1,1;]"..
|
||||
"item_image[6,1;1,1;farming:flour]"..
|
||||
"image[6,1;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
if techage.ta1_mill_has_power(pos, 2) then
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack("src", 1)
|
||||
if not stack:is_empty() then
|
||||
local name = stack:get_name()
|
||||
if RecipesTa1[name] then
|
||||
local recipe = RecipesTa1[name]
|
||||
src_to_dst(stack, 1, name, 1, recipe.inp_num, inv, recipe.output)
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta1_mill_base", {
|
||||
description = S("TA1 Mill Base"),
|
||||
tiles = {
|
||||
"techage_mill_base.png",
|
||||
"default_stone_brick.png",
|
||||
},
|
||||
after_place_node = function(pos, placer)
|
||||
M(pos):set_string("formspec", formspecStr)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 1)
|
||||
inv:set_size('dst', 1)
|
||||
minetest.get_node_timer(pos):start(4)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
on_timer = node_timer,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, crumbly = 2, choppy = 2},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta1_mill_base"}, {
|
||||
on_node_load = function(pos, node)
|
||||
minetest.get_node_timer(pos):start(4)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta1_mill_base",
|
||||
recipe = {
|
||||
{"default:stonebrick", "", "default:stonebrick"},
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"default:stonebrick", "", "default:stonebrick"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "techage:hammer_steel", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("grinding", {
|
||||
description = S("Grinding"),
|
||||
icon = 'techage_appl_grinder.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
techage.recipes.register_craft_type("milling", {
|
||||
description = S("Milling"),
|
||||
icon = 'techage_mill_inv.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
|
||||
function techage.add_grinder_recipe(recipe, ta1_permitted)
|
||||
local name, num = unpack(string.split(recipe.input, " ", false, 1))
|
||||
if minetest.registered_items[name] then
|
||||
if ta1_permitted then
|
||||
RecipesTa1[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
|
||||
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "milling"
|
||||
techage.recipes.register_craft(table.copy(recipe))
|
||||
end
|
||||
|
||||
Recipes[name] = {input = name,inp_num = tonumber(num) or 1, output = recipe.output}
|
||||
|
||||
recipe.items = {recipe.input}
|
||||
recipe.type = "grinding"
|
||||
techage.recipes.register_craft(recipe)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
techage.add_grinder_recipe({input="default:cobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:desert_cobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:mossycobble", output="default:gravel"})
|
||||
techage.add_grinder_recipe({input="default:gravel", output="default:sand"})
|
||||
techage.add_grinder_recipe({input="techage:sieved_gravel", output="default:sand"})
|
||||
techage.add_grinder_recipe({input="default:coral_skeleton", output="default:silver_sand"})
|
||||
|
||||
if minetest.global_exists("skytest") then
|
||||
techage.add_grinder_recipe({input="default:desert_sand", output="skytest:dust"})
|
||||
techage.add_grinder_recipe({input="default:silver_sand", output="skytest:dust"})
|
||||
techage.add_grinder_recipe({input="default:sand", output="skytest:dust"})
|
||||
else
|
||||
techage.add_grinder_recipe({input="default:desert_sand", output="default:clay"})
|
||||
techage.add_grinder_recipe({input="default:silver_sand", output="default:clay"})
|
||||
techage.add_grinder_recipe({input="default:sand", output="default:clay"})
|
||||
end
|
||||
|
||||
techage.add_grinder_recipe({input="default:sandstone", output="default:sand 4"})
|
||||
techage.add_grinder_recipe({input="default:desert_sandstone", output="default:desert_sand 4"})
|
||||
techage.add_grinder_recipe({input="default:silver_sandstone", output="default:silver_sand 4"})
|
||||
|
||||
techage.add_grinder_recipe({input="default:tree", output="default:leaves 8"})
|
||||
techage.add_grinder_recipe({input="default:jungletree", output="default:jungleleaves 8"})
|
||||
techage.add_grinder_recipe({input="default:pine_tree", output="default:pine_needles 8"})
|
||||
techage.add_grinder_recipe({input="default:acacia_tree", output="default:acacia_leaves 8"})
|
||||
techage.add_grinder_recipe({input="default:aspen_tree", output="default:aspen_leaves 8"})
|
||||
|
||||
if minetest.global_exists("farming") then
|
||||
techage.add_grinder_recipe({input="farming:wheat 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_wheat 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:barley 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_barley 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:rye 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_rye 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:rice 3", output="farming:rice_flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_rice 6", output="farming:rice_flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:oat 3", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_oat 6", output="farming:flour"}, true)
|
||||
techage.add_grinder_recipe({input="farming:seed_cotton 3", output="basic_materials:oil_extract"}, true)
|
||||
end
|
@ -1,106 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Item Source Block
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local CYCLE_TIME = 30
|
||||
|
||||
local function formspec()
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;3.5,0.8;1,1;]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
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
|
||||
|
||||
return stack:get_count()
|
||||
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
|
||||
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
minetest.register_node("techage:itemsource", {
|
||||
description = "Techage Item Source",
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_outp.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_nodedetector.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_nodedetector.png^techage_frame_ta3.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
meta:set_string("infotext", "Techage Item Source")
|
||||
meta:set_string("formspec", formspec())
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
local meta = M(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack('main', 1)
|
||||
if stack:get_count() > 0 then
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
local leftover = techage.push_items(pos, push_dir, stack)
|
||||
local pushed
|
||||
if not leftover then
|
||||
pushed = 0
|
||||
elseif leftover ~= true then
|
||||
pushed = stack:get_count() - leftover:get_count()
|
||||
else -- leftover == true
|
||||
pushed = stack:get_count()
|
||||
end
|
||||
meta:set_int("counter", pushed)
|
||||
meta:set_string("infotext", "Techage Item Source: "..pushed)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir", -- important!
|
||||
on_rotate = screwdriver.disallow, -- important!
|
||||
is_ground_content = false,
|
||||
drop = "",
|
||||
groups = {crumbly = 3, cracky = 3, snappy = 3},
|
||||
sounds = default.node_sound_glass_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:itemsource"}, {
|
||||
on_node_load = function(pos)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end,
|
||||
})
|
@ -1,228 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3 Bucket based Liquid Sampler
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 3
|
||||
local CYCLE_TIME = 8
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[9,8.5]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;1,4;]"..
|
||||
"image[0,0;1,1;bucket.png]"..
|
||||
"image[1,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[1,1.5;1,1;techage_form_arrow.png]"..
|
||||
"image_button[1,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[1,3;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;2,0;7,4;]"..
|
||||
"list[current_player;main;0.5,4.5;8,4;]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]" ..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;dst]" ..
|
||||
"listring[current_player;main]"
|
||||
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
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function is_water(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local liquiddef = bucket.liquids[node.name]
|
||||
if liquiddef ~= nil and liquiddef.itemname ~= nil and node.name == liquiddef.source then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
local water_pos = minetest.string_to_pos(M(pos):get_string("water_pos"))
|
||||
if not is_water(water_pos) then
|
||||
return S("no usable water")
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function sample_liquid(pos, crd, nvm, inv)
|
||||
if inv:room_for_item("dst", {name = "bucket:bucket_water"}) and
|
||||
inv:contains_item("src", {name = "bucket:bucket_empty"}) then
|
||||
inv:remove_item("src", {name = "bucket:bucket_empty"})
|
||||
inv:add_item("dst", {name = "bucket:bucket_water"})
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
--if tubelib.data_not_corrupted(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
sample_liquid(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^{power}^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_liquidsampler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^{power}^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_filling4_ta#.png^techage_liquidsampler4.png^techage_frame4_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_appl_liquidsampler.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, _ =
|
||||
techage.register_consumer("liquidsampler", S("Liquid Sampler"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
can_start = can_start,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size("src", 4)
|
||||
inv:set_size("dst", 28)
|
||||
local water_pos = techage.get_pos(pos, "B")
|
||||
M(pos):set_string("water_pos", minetest.pos_to_string(water_pos))
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,2,4},
|
||||
power_consumption = {0,3,5,8},
|
||||
power_sides = {U=1},
|
||||
},
|
||||
{false, true, true, false}) -- TA2/A3
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "bucket:bucket_empty", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
@ -1,131 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube support for digtron and protector chests
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
|
||||
local CacheForFuelNodeNames = {}
|
||||
|
||||
local function is_fuel(stack)
|
||||
local name = stack:get_name()
|
||||
if CacheForFuelNodeNames[name] then
|
||||
return true
|
||||
end
|
||||
if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
|
||||
CacheForFuelNodeNames[name] = true
|
||||
end
|
||||
return CacheForFuelNodeNames[name]
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- digtron
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
techage.register_node({"digtron:inventory"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"digtron:fuelstore"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "fuel"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "fuel", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"digtron:combined_storage"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
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, side, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
minetest.get_node_timer(pos):start(1.0)
|
||||
if is_fuel(stack) then
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
else
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, side, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- protector
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
techage.register_node({"protector:chest"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
@ -1,438 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3/TA4 Pusher
|
||||
Nodes for push/pull operation of StackItems from chests or other
|
||||
inventory/server nodes to tubes or other inventory/server nodes.
|
||||
|
||||
+--------+
|
||||
/ /|
|
||||
+--------+ |
|
||||
IN (L) -->| |X--> OUT (R)
|
||||
| PUSHER | +
|
||||
| |/
|
||||
+--------+
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local Tube = techage.Tube
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local WRENCH_MENU = {
|
||||
{
|
||||
type = "number",
|
||||
name = "limit",
|
||||
label = S("Number of items"),
|
||||
tooltip = S("Number of items that are allowed to be pushed"),
|
||||
default = "0",
|
||||
},
|
||||
}
|
||||
|
||||
local function ta4_formspec(self, pos, nvm)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize("#000000", S("Pusher")).."]"..
|
||||
techage.question_mark_help(7.5, S("Optionally configure\nthe pusher with one item"))..
|
||||
techage.wrench_image(7.4, -0.05) ..
|
||||
"list[context;main;3.5,0.8;1,1;]"..
|
||||
"image_button[3.5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
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 nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
if list[index]:get_count() == 0 then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
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
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function set_limit(pos, nvm, val)
|
||||
val = tonumber(val) or 0
|
||||
if val > 0 then
|
||||
nvm.limit = val
|
||||
nvm.num_items = 0
|
||||
M(pos):set_int("limit", val)
|
||||
else
|
||||
nvm.limit = nil
|
||||
nvm.num_items = nil
|
||||
M(pos):set_string("limit", "")
|
||||
end
|
||||
end
|
||||
|
||||
-- Function returns the number of pushed items
|
||||
local function push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
local items = techage.pull_items(pos, pull_dir, num, nvm.item_name)
|
||||
if items ~= nil then
|
||||
local taken = items:get_count()
|
||||
local leftover = techage.push_items(pos, push_dir, items)
|
||||
if not leftover then
|
||||
-- place item back
|
||||
techage.unpull_items(pos, pull_dir, items)
|
||||
crd.State:blocked(pos, nvm)
|
||||
return 0
|
||||
elseif leftover ~= true then
|
||||
-- place item back
|
||||
taken = taken - leftover:get_count()
|
||||
techage.unpull_items(pos, pull_dir, leftover)
|
||||
crd.State:blocked(pos, nvm)
|
||||
return taken
|
||||
end
|
||||
return taken
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function pushing(pos, crd, meta, nvm)
|
||||
local pull_dir = meta:get_int("pull_dir")
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
|
||||
if not nvm.limit then
|
||||
local num = nvm.item_count or nvm.num_items or crd.num_items
|
||||
num = push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
if num > 0 then
|
||||
if nvm.item_count then
|
||||
nvm.item_count = nvm.item_count - num
|
||||
if nvm.item_count <= 0 then
|
||||
crd.State:stop(pos, nvm)
|
||||
nvm.item_count = nil
|
||||
end
|
||||
end
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
elseif nvm.num_items < nvm.limit then
|
||||
local num = math.min(crd.num_items, nvm.limit - nvm.num_items)
|
||||
num = push(pos, crd, meta, nvm, pull_dir, push_dir, num)
|
||||
if num > 0 then
|
||||
nvm.num_items = nvm.num_items + num
|
||||
if nvm.num_items >= nvm.limit then
|
||||
crd.State:stop(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
pushing(pos, crd, M(pos), nvm)
|
||||
crd.State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if CRD(pos).stage ~= 4 then -- Not TA4 node?
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
if CRD(pos).State:get_state(nvm) == techage.STOPPED then
|
||||
CRD(pos).State:start(pos, nvm)
|
||||
else
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", ta4_formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
local pull_dir = M(pos):get_int("pull_dir")
|
||||
local push_dir = M(pos):get_int("push_dir")
|
||||
local is_ta4_tube = true
|
||||
|
||||
for i, pos, node in Tube:get_tube_line(pos, pull_dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
for i, pos, node in Tube:get_tube_line(pos, push_dir) do
|
||||
is_ta4_tube = is_ta4_tube and techage.TA4tubes[node.name]
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
if CRD(pos).stage == 4 and not is_ta4_tube then
|
||||
nvm.num_items = crd.num_items / 2
|
||||
else
|
||||
nvm.num_items = crd.num_items
|
||||
end
|
||||
end
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
local inv = M(pos):get_inventory()
|
||||
local name = inv:get_stack("main", 1):get_name()
|
||||
if name ~= "" then
|
||||
nvm.item_name = name
|
||||
else
|
||||
nvm.item_name = nil
|
||||
end
|
||||
else
|
||||
nvm.item_name = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function ta_after_formspec(pos, fields, playername)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
set_limit(pos, nvm, fields.limit)
|
||||
end
|
||||
|
||||
local function on_state_change(pos, old_state, new_state)
|
||||
if old_state == techage.STOPPED and new_state == techage.RUNNING then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
set_limit(pos, nvm, M(pos):get_int("limit"))
|
||||
end
|
||||
end
|
||||
|
||||
local function config_item(pos, payload)
|
||||
if type(payload) == "string" then
|
||||
if payload == "" then
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack("main", 1, nil)
|
||||
return 0
|
||||
else
|
||||
local name, count = unpack(payload:split(" "))
|
||||
if name and (minetest.registered_nodes[name] or minetest.registered_items[name]
|
||||
or minetest.registered_craftitems[name]) then
|
||||
count = tonumber(count) or 1
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack("main", 1, {name = name, count = 1})
|
||||
return count
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_appl_pusher.png^[transformR180]^techage_frame_ta#.png",
|
||||
"techage_appl_pusher.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_appl_pusher14.png^techage_frame14_ta#.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
-- push item through the pusher in opposit direction
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
return in_dir == M(pos):get_int("pull_dir") and techage.safe_push_items(pos, in_dir, stack)
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "pull" then -- Deprecated command, use config/limit/start instead
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
nvm.item_count = math.min(config_item(pos, payload), 12)
|
||||
nvm.rmt_num = src
|
||||
CRD(pos).State:start(pos, nvm)
|
||||
return true
|
||||
elseif topic == "config" then -- Set item type
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
config_item(pos, payload)
|
||||
return true
|
||||
elseif topic == "limit" then -- Set push limit
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
set_limit(pos, nvm, payload)
|
||||
return true
|
||||
elseif topic == "count" then -- Get number of push items
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return nvm.num_items or 0
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
if topic == 65 then -- Set item type
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
config_item(pos, payload)
|
||||
return 0
|
||||
elseif topic == 68 or topic == 20 then -- Set push limit
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
set_limit(pos, nvm, payload[1])
|
||||
return 0
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.limit then
|
||||
nvm.num_items = 0
|
||||
end
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 150 then -- Get number of pushed items
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {nvm.num_items or 0}
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("pusher", S("Pusher"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = ta4_formspec,
|
||||
tubing = tubing,
|
||||
can_start = can_start,
|
||||
on_state_change = on_state_change,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
if CRD(pos).stage == 4 then -- TA4 node?
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", ta4_formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
local meta = M(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", new_param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
end,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
on_rightclick = on_rightclick,
|
||||
on_receive_fields = on_receive_fields,
|
||||
node_timer = keep_running,
|
||||
on_rotate = screwdriver.disallow,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
ta4_formspec = WRENCH_MENU,
|
||||
ta_after_formspec = ta_after_formspec,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,2,6,12},
|
||||
tube_sides = {L=1, R=1},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2.." 2",
|
||||
recipe = {
|
||||
{"group:wood", "wool:dark_green", "group:wood"},
|
||||
{"techage:tubeS", "default:mese_crystal", "techage:tubeS"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:iron_ingot", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
@ -1,457 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Quarry machine to dig stones and other ground blocks.
|
||||
|
||||
The Quarry digs a hole (default) 5x5 blocks large and up to 80 blocks deep.
|
||||
It starts at the given level (0 is same level as the quarry block,
|
||||
1 is one level higher and so on)) and goes down to the given depth number.
|
||||
It digs one block every 4 seconds.
|
||||
|
||||
]]--
|
||||
|
||||
-- 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
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local CYCLE_TIME = 4
|
||||
local STANDBY_TICKS = 4
|
||||
local COUNTDOWN_TICKS = 4
|
||||
|
||||
local Side2Facedir = {F=0, R=1, B=2, L=3, D=4, U=5}
|
||||
local Depth2Idx = {[1]=1 ,[2]=2, [3]=3, [5]=4, [7]=5, [10]=6, [15]=7, [20]=8, [25]=9, [40]=10, [60]=11, [80]=12}
|
||||
local Holesize2Idx = {["3x3"] = 1, ["5x5"] = 2, ["7x7"] = 3, ["9x9"] = 4, ["11x11"] = 5}
|
||||
local Holesize2Diameter = {["3x3"] = 3, ["5x5"] = 5, ["7x7"] = 7, ["9x9"] = 9, ["11x11"] = 11}
|
||||
local Level2Idx = {[2]=1, [1]=2, [0]=3, [-1]=4, [-2]=5, [-3]=6,
|
||||
[-5]=7, [-10]=8, [-15]=9, [-20]=10}
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local tooltip = S("Start level = 0\nmeans the same level\nas the quarry is placed")
|
||||
local level_idx = Level2Idx[nvm.start_level or 1] or 2
|
||||
local depth_idx = Depth2Idx[nvm.quarry_depth or 1] or 1
|
||||
local hsize_idx = Holesize2Idx[nvm.hole_size or "5x5"] or 2
|
||||
local level = nvm.level or "-"
|
||||
local hsize_list = "5x5"
|
||||
if CRD(pos).stage == 4 then
|
||||
hsize_list = "3x3,5x5,7x7,9x9,11x11"
|
||||
elseif CRD(pos).stage == 3 then
|
||||
hsize_list = "3x3,5x5,7x7"
|
||||
end
|
||||
local depth_list = "1,2,3,5,7,10,15,20,25,40,60,80"
|
||||
if CRD(pos).stage == 3 then
|
||||
depth_list = "1,2,3,5,7,10,15,20,25,40"
|
||||
elseif CRD(pos).stage == 2 then
|
||||
depth_list = "1,2,3,5,7,10,15,20"
|
||||
end
|
||||
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3.5,-0.1;"..minetest.colorize( "#000000", S("Quarry")).."]"..
|
||||
techage.question_mark_help(8, tooltip)..
|
||||
"dropdown[0,0.8;1.5;level;2,1,0,-1,-2,-3,-5,-10,-15,-20;"..level_idx.."]"..
|
||||
"label[1.6,0.9;"..S("Start level").."]"..
|
||||
"dropdown[0,1.8;1.5;depth;"..depth_list..";"..depth_idx.."]"..
|
||||
"label[1.6,1.9;"..S("Digging depth").." ("..level..")]"..
|
||||
"dropdown[0,2.8;1.5;hole_size;"..hsize_list..";"..hsize_idx.."]"..
|
||||
"label[1.6,2.9;"..S("Hole size").."]"..
|
||||
"list[context;main;5,0.8;3,3;]"..
|
||||
"image[4,0.8;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image_button[4,2.8;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[4,2.8;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[current_player;main;0,4.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function play_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.handle or mem.handle == -1 then
|
||||
mem.handle = minetest.sound_play("techage_quarry", {
|
||||
pos = pos,
|
||||
gain = 1.5,
|
||||
max_hear_distance = 15,
|
||||
loop = true})
|
||||
if mem.handle == -1 then
|
||||
minetest.after(1, play_sound, pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if mem.handle then
|
||||
minetest.sound_stop(mem.handle)
|
||||
mem.handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function on_node_state_change(pos, old_state, new_state)
|
||||
local mem = techage.get_mem(pos)
|
||||
local owner = M(pos):get_string("owner")
|
||||
mem.co = nil
|
||||
techage.unmark_position(owner)
|
||||
if new_state == techage.RUNNING then
|
||||
play_sound(pos)
|
||||
else
|
||||
stop_sound(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_pos(pos, facedir, side, steps)
|
||||
facedir = (facedir + Side2Facedir[side]) % 4
|
||||
local dir = vector.multiply(minetest.facedir_to_dir(facedir), steps or 1)
|
||||
return vector.add(pos, dir)
|
||||
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
|
||||
return stack:get_count()
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
|
||||
local function get_quarry_pos(pos, xoffs, zoffs)
|
||||
return {x = pos.x + xoffs - 1, y = pos.y, z = pos.z + zoffs - 1}
|
||||
end
|
||||
|
||||
-- pos is the quarry pos
|
||||
local function get_corner_positions(pos, facedir, hole_diameter)
|
||||
local _pos = get_pos(pos, facedir, "L")
|
||||
local pos1 = get_pos(_pos, facedir, "F", math.floor((hole_diameter - 1) / 2))
|
||||
local pos2 = get_pos(_pos, facedir, "B", math.floor((hole_diameter - 1) / 2))
|
||||
pos2 = get_pos(pos2, facedir, "L", hole_diameter - 1)
|
||||
if pos1.x > pos2.x then pos1.x, pos2.x = pos2.x, pos1.x end
|
||||
if pos1.y > pos2.y then pos1.y, pos2.y = pos2.y, pos1.y end
|
||||
if pos1.z > pos2.z then pos1.z, pos2.z = pos2.z, pos1.z end
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
local function is_air_level(pos1, pos2, hole_diameter)
|
||||
return #minetest.find_nodes_in_area(pos1, pos2, {"air"}) == hole_diameter * hole_diameter
|
||||
end
|
||||
|
||||
local function mark_area(pos1, pos2, owner)
|
||||
pos1.y = pos1.y + 0.2
|
||||
techage.mark_cube(owner, pos1, pos2, "quarry", "#FF0000", 20)
|
||||
pos1.y = pos1.y - 0.2
|
||||
end
|
||||
|
||||
local function quarry_task(pos, crd, nvm)
|
||||
nvm.start_level = nvm.start_level or 0
|
||||
nvm.quarry_depth = nvm.quarry_depth or 1
|
||||
nvm.hole_diameter = nvm.hole_diameter or 5
|
||||
local y_first = pos.y + nvm.start_level
|
||||
local y_last = y_first - nvm.quarry_depth + 1
|
||||
local facedir = minetest.get_node(pos).param2
|
||||
local owner = M(pos):get_string("owner")
|
||||
local fake_player = techage.Fake_player:new()
|
||||
fake_player.get_pos = function (...)
|
||||
return pos
|
||||
end
|
||||
fake_player.get_inventory = function(...)
|
||||
return M(pos):get_inventory()
|
||||
end
|
||||
|
||||
local add_to_inv = function(itemstacks)
|
||||
local at_least_one_added = false
|
||||
local inv = M(pos):get_inventory()
|
||||
if #itemstacks == 0 then
|
||||
return true
|
||||
end
|
||||
for _,stack in ipairs(itemstacks) do
|
||||
if inv:room_for_item("main", stack) then
|
||||
inv:add_item("main", stack)
|
||||
at_least_one_added = true
|
||||
elseif at_least_one_added then
|
||||
minetest.add_item({x=pos.x,y=pos.y+1,z=pos.z}, stack)
|
||||
end
|
||||
end
|
||||
return at_least_one_added
|
||||
end
|
||||
|
||||
local pos1, pos2 = get_corner_positions(pos, facedir, nvm.hole_diameter)
|
||||
nvm.level = 1
|
||||
for y_curr = y_first, y_last, -1 do
|
||||
pos1.y = y_curr
|
||||
pos2.y = y_curr
|
||||
|
||||
-- Restarting the server can detach the coroutine data.
|
||||
-- Therefore, read nvm again.
|
||||
nvm = techage.get_nvm(pos)
|
||||
nvm.level = y_first - y_curr
|
||||
|
||||
if minetest.is_area_protected(pos1, pos2, owner, 5) then
|
||||
crd.State:fault(pos, nvm, S("area is protected"))
|
||||
return
|
||||
end
|
||||
|
||||
if not is_air_level(pos1, pos2, nvm.hole_diameter) then
|
||||
mark_area(pos1, pos2, owner)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
coroutine.yield()
|
||||
|
||||
for zoffs = 1, nvm.hole_diameter do
|
||||
for xoffs = 1, nvm.hole_diameter do
|
||||
local qpos = get_quarry_pos(pos1, xoffs, zoffs)
|
||||
local dig_state = techage.dig_like_player(qpos, fake_player, add_to_inv)
|
||||
|
||||
if dig_state == techage.dig_states.INV_FULL then
|
||||
crd.State:blocked(pos, nvm, S("inventory full"))
|
||||
coroutine.yield()
|
||||
elseif dig_state == techage.dig_states.DUG then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
end
|
||||
techage.unmark_position(owner)
|
||||
end
|
||||
end
|
||||
crd.State:stop(pos, nvm, S("finished"))
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.co then
|
||||
mem.co = coroutine.create(quarry_task)
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local _, err = coroutine.resume(mem.co, pos, crd, nvm)
|
||||
if err then
|
||||
minetest.log("error", "[TA4 Quarry Coroutine Error] at pos " .. minetest.pos_to_string(pos) .. " " .. err)
|
||||
end
|
||||
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(crd.State, pos, nvm))
|
||||
end
|
||||
if nvm.techage_state ~= techage.RUNNING then
|
||||
stop_sound(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("main")
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
|
||||
if fields.depth then
|
||||
if tonumber(fields.depth) ~= nvm.quarry_depth then
|
||||
nvm.quarry_depth = tonumber(fields.depth)
|
||||
if CRD(pos).stage == 2 then
|
||||
nvm.quarry_depth = math.min(nvm.quarry_depth, 20)
|
||||
elseif CRD(pos).stage == 3 then
|
||||
nvm.quarry_depth = math.min(nvm.quarry_depth, 40)
|
||||
end
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
if fields.level then
|
||||
if tonumber(fields.level) ~= nvm.start_level then
|
||||
nvm.start_level = tonumber(fields.level)
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
if fields.hole_size then
|
||||
if CRD(pos).stage == 4 then
|
||||
if fields.hole_size ~= nvm.hole_size then
|
||||
nvm.hole_size = fields.hole_size
|
||||
nvm.hole_diameter = Holesize2Diameter[fields.hole_size or "5x5"] or 5
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
elseif CRD(pos).stage == 3 then
|
||||
if fields.hole_size ~= nvm.hole_size then
|
||||
nvm.hole_size = fields.hole_size
|
||||
nvm.hole_diameter = Holesize2Diameter[fields.hole_size or "7x7"] or 7
|
||||
mem.co = nil
|
||||
CRD(pos).State:stop(pos, nvm)
|
||||
end
|
||||
else
|
||||
nvm.hole_size = "5x5"
|
||||
nvm.hole_diameter = 5
|
||||
end
|
||||
end
|
||||
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_quarry_left.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
{
|
||||
name = "techage_frame14_ta#.png^techage_quarry_left14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_quarry.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "depth" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return nvm.level or 0
|
||||
else
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 133 then -- Quarry Depth
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {nvm.level or 0}
|
||||
else
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.techage_state == techage.RUNNING then
|
||||
stop_sound(pos)
|
||||
play_sound(pos)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("quarry", S("Quarry"), tiles, {
|
||||
drawtype = "normal",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
on_state_change = on_node_state_change,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
local nvm = techage.get_nvm(pos)
|
||||
inv:set_size('main', 9)
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,1,1,1},
|
||||
power_consumption = {0,10,12,14},
|
||||
}
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta2,
|
||||
recipe = {
|
||||
{"group:wood", "default:mese_crystal", "group:wood"},
|
||||
{"techage:tubeS", "default:pick_diamond", "techage:iron_ingot"},
|
||||
{"group:wood", "techage:iron_ingot", "group:wood"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta2, ""},
|
||||
{"", "techage:vacuum_tube", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", node_name_ta3, ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
@ -1,243 +0,0 @@
|
||||
--[[
|
||||
|
||||
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"},
|
||||
},
|
||||
})
|
@ -1,358 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Recycler, recycling techage machines
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 8
|
||||
|
||||
local Recipes = {}
|
||||
|
||||
local SpecialItems = {
|
||||
["techage:sieved_gravel"] = "default:sand",
|
||||
["basic_materials:heating_element"] = "default:copper_ingot",
|
||||
["techage:ta4_wlanchip"] = "",
|
||||
["techage:basalt_cobble"] = "default:sand",
|
||||
["default:stone"] = "techage:sieved_gravel",
|
||||
["default:wood"] = "default:stick 5",
|
||||
["basic_materials:concrete_block"] = "techage:sieved_gravel",
|
||||
["dye:green"] = "",
|
||||
["dye:red"] = "",
|
||||
["dye:white"] = "",
|
||||
["dye:blue"] = "",
|
||||
["dye:brown"] = "",
|
||||
["dye:cyan"] = "",
|
||||
["dye:yellow"] = "",
|
||||
["dye:grey"] = "",
|
||||
["dye:orange"] = "",
|
||||
["dye:black"] = "",
|
||||
["techage:basalt_glass_thin"] = "",
|
||||
["group:stone"] = "techage:sieved_gravel",
|
||||
--["basic_materials:plastic_sheet"] = "",
|
||||
["group:wood"] = "default:stick 5",
|
||||
["techage:basalt_glass"] = "",
|
||||
["default:junglewood"] = "default:stick 5",
|
||||
["techage:ta4_silicon_wafer"] = "",
|
||||
["default:cobble"] = "techage:sieved_gravel",
|
||||
["default:pick_diamond"] = "default:stick",
|
||||
["techage:hammer_steel"] = "default:stick",
|
||||
["default:paper"] = "",
|
||||
["stairs:slab_basalt_glass2"] = "",
|
||||
["techage:basalt_stone"] = "techage:sieved_gravel",
|
||||
["techage:ta4_ramchip"] = "",
|
||||
["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)
|
||||
return "size[8,8]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;src;0,0;3,3;]"..
|
||||
--"item_image[0,0;1,1;default:cobble]"..
|
||||
"image[0,0;1,1;techage_form_mask.png]"..
|
||||
"image[3.5,0;1,1;"..techage.get_power_image(pos, nvm).."]"..
|
||||
"image[3.5,1;1,1;techage_form_arrow.png]"..
|
||||
"image_button[3.5,2;1,1;"..self:get_state_button_image(nvm)..";state_button;]"..
|
||||
"tooltip[3.5,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"list[context;dst;5,0;3,3;]"..
|
||||
--"item_image[5,0;1,1;default:gravel]"..
|
||||
"image[5,0;1,1;techage_form_mask.png]"..
|
||||
"list[current_player;main;0,4;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 4)
|
||||
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
|
||||
if listname == "src" then
|
||||
CRD(pos).State:start_if_standby(pos)
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function cook_reverse(stack, inv, idx, recipe)
|
||||
-- check space
|
||||
for _,item in ipairs(recipe.items) do
|
||||
if not inv:room_for_item("dst", item) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- take item
|
||||
inv:remove_item("src", ItemStack(recipe.output))
|
||||
-- add items
|
||||
for _,item in ipairs(recipe.items) do
|
||||
inv:add_item("dst", item)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function get_recipe(stack)
|
||||
local name = stack:get_name()
|
||||
local recipe = Recipes[name]
|
||||
if recipe then
|
||||
if stack:get_count() >= ItemStack(recipe.output):get_count() then
|
||||
return recipe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function recycling(pos, crd, nvm, inv)
|
||||
for idx,stack in ipairs(inv:get_list("src")) do
|
||||
local recipe = not stack:is_empty() and get_recipe(stack)
|
||||
if recipe then
|
||||
if cook_reverse(stack, inv, idx, recipe) then
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:blocked(pos, nvm)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
recycling(pos, crd, nvm, inv)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("dst") and inv:is_empty("src")
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_appl_grinder.png^[colorize:@@000000:100^techage_frame_ta#_top.png",
|
||||
--"techage_appl_grinder.png^techage_frame_ta#_top.png^[multiply:#FF0000",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_appl_grinder4.png^[colorize:@@000000:100^techage_frame4_ta#_top.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 1.0,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
"techage_filling_ta#.png^techage_appl_recycler.png^techage_frame_ta#.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.get_items(pos, inv, "dst", num)
|
||||
end
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
|
||||
local inv = M(pos):get_inventory()
|
||||
--CRD(pos).State:start_if_standby(pos) -- would need power!
|
||||
return techage.put_items(inv, "src", stack)
|
||||
end
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("pull_dir") == in_dir then
|
||||
local inv = M(pos):get_inventory()
|
||||
return techage.put_items(inv, "dst", stack)
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local _, _, node_name_ta4 =
|
||||
techage.register_consumer("recycler", S("Recycler"), tiles, {
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, -8/16, -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},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, -8/16, -6/16, 6/16, 6/16, 6/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('src', 9)
|
||||
inv:set_size('dst', 9)
|
||||
end,
|
||||
can_dig = can_dig,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,0,0,1},
|
||||
power_consumption = {0,0,0,16},
|
||||
},
|
||||
{false, false, false, true}) -- TA4 only
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "default:mese_crystal", ""},
|
||||
{"", "techage:ta4_grinder_pas", ""},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Prepare recipes
|
||||
-------------------------------------------------------------------------------
|
||||
-- Nodes from mods that can be recycled
|
||||
local ModNames = {
|
||||
techage = true,
|
||||
hyperloop = true,
|
||||
}
|
||||
|
||||
local function get_item_list(inputs)
|
||||
local lst = {}
|
||||
for _,input in pairs(inputs or {}) do
|
||||
if SpecialItems[input] then
|
||||
input = SpecialItems[input]
|
||||
end
|
||||
if input and input ~= "" then
|
||||
if minetest.registered_nodes[input] or minetest.registered_items[input] then
|
||||
table.insert(lst, input)
|
||||
end
|
||||
end
|
||||
end
|
||||
return lst
|
||||
end
|
||||
|
||||
local function get_special_recipe(name)
|
||||
if SpecialItems[name] then
|
||||
return {
|
||||
output = name,
|
||||
items = {SpecialItems[name]}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function collect_recipes()
|
||||
local add = function(name, ndef)
|
||||
local _, _, mod, _ = string.find(name, "([%w_]+):([%w_]+)")
|
||||
local recipe = get_special_recipe(name) or
|
||||
techage.recipes.get_recipe(name) or
|
||||
minetest.get_craft_recipe(name)
|
||||
local items = get_item_list(recipe.items)
|
||||
|
||||
if ModNames[mod]
|
||||
and ndef.groups.not_in_creative_inventory ~= 1
|
||||
and not ndef.tool_capabilities
|
||||
and recipe.output
|
||||
and next(items) then
|
||||
local s = table.concat(items, ", ")
|
||||
--print(string.format("%-36s {%s}", recipe.output, s))
|
||||
Recipes[name] = {output = recipe.output, items = items}
|
||||
end
|
||||
end
|
||||
|
||||
for name, ndef in pairs(minetest.registered_nodes) do
|
||||
add(name, ndef)
|
||||
end
|
||||
for name, ndef in pairs(minetest.registered_items) do
|
||||
add(name, ndef)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.after(2, collect_recipes)
|
@ -1,265 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA2/TA3 Power Test Source
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Axle = techage.Axle
|
||||
--local Pipe = techage.SteamPipe
|
||||
local Cable = techage.ElectricCable
|
||||
local power = networks.power
|
||||
local control = networks.control
|
||||
|
||||
local STANDBY_TICKS = 4
|
||||
local CYCLE_TIME = 2
|
||||
local PWR_PERF = 100
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return techage.generator_formspec(self, pos, nvm, S("Power Source"), nvm.provided, PWR_PERF)
|
||||
end
|
||||
|
||||
-- Axles texture animation
|
||||
local function switch_axles(pos, on)
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
Axle:switch_tube_line(pos, outdir, on and "on" or "off")
|
||||
end
|
||||
|
||||
local function start_node2(pos, nvm, state)
|
||||
nvm.running = true
|
||||
nvm.provided = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
switch_axles(pos, true)
|
||||
power.start_storage_calc(pos, Axle, outdir)
|
||||
end
|
||||
|
||||
local function stop_node2(pos, nvm, state)
|
||||
nvm.running = false
|
||||
nvm.provided = 0
|
||||
nvm.load = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
switch_axles(pos, false)
|
||||
power.start_storage_calc(pos, Axle, outdir)
|
||||
end
|
||||
|
||||
local function start_node3(pos, nvm, state)
|
||||
local meta = M(pos)
|
||||
nvm.running = true
|
||||
nvm.provided = 0
|
||||
techage.evaluate_charge_termination(nvm, meta)
|
||||
local outdir = meta:get_int("outdir")
|
||||
power.start_storage_calc(pos, Cable, outdir)
|
||||
end
|
||||
|
||||
local function stop_node3(pos, nvm, state)
|
||||
nvm.running = false
|
||||
nvm.provided = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
power.start_storage_calc(pos, Cable, outdir)
|
||||
end
|
||||
|
||||
local State2 = techage.NodeStates:new({
|
||||
node_name_passive = "techage:t2_source",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec_func = formspec,
|
||||
start_node = start_node2,
|
||||
stop_node = stop_node2,
|
||||
})
|
||||
|
||||
local State3 = techage.NodeStates:new({
|
||||
node_name_passive = "techage:t4_source",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec_func = formspec,
|
||||
start_node = start_node3,
|
||||
stop_node = stop_node3,
|
||||
})
|
||||
|
||||
local function node_timer2(pos, elapsed)
|
||||
--print("node_timer2")
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local outdir = meta:get_int("outdir")
|
||||
local tp1 = tonumber(meta:get_string("termpoint1"))
|
||||
local tp2 = tonumber(meta:get_string("termpoint2"))
|
||||
nvm.provided = power.provide_power(pos, Axle, outdir, PWR_PERF, tp1, tp2)
|
||||
nvm.load = power.get_storage_load(pos, Axle, outdir, PWR_PERF)
|
||||
if techage.is_activeformspec(pos) then
|
||||
meta:set_string("formspec", formspec(State2, pos, nvm))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function node_timer3(pos, elapsed)
|
||||
--print("node_timer4")
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
local tp1 = tonumber(meta:get_string("termpoint1"))
|
||||
local tp2 = tonumber(meta:get_string("termpoint2"))
|
||||
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
|
||||
nvm.load = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
|
||||
if techage.is_activeformspec(pos) then
|
||||
meta:set_string("formspec", formspec(State3, pos, nvm))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function on_receive_fields2(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
State2:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(State2, pos, nvm))
|
||||
end
|
||||
|
||||
local function on_receive_fields3(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
State3:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(State3, pos, nvm))
|
||||
end
|
||||
|
||||
local function on_rightclick2(pos, node, clicker)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(State2, pos, nvm))
|
||||
end
|
||||
|
||||
local function on_rightclick3(pos, node, clicker)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(State3, pos, nvm))
|
||||
end
|
||||
|
||||
local function after_place_node2(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
State2:node_init(pos, nvm, "")
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_string("formspec", formspec(State2, pos, nvm))
|
||||
Axle:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_place_node3(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local number = techage.add_node(pos, "techage:t4_source")
|
||||
State3:node_init(pos, nvm, number)
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_string("formspec", formspec(State3, pos, nvm))
|
||||
Cable:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node2(pos, oldnode)
|
||||
Axle:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node3(pos, oldnode)
|
||||
Cable:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function get_generator_data(pos, outdir, tlib2)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.running then
|
||||
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 2}
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:t2_source", {
|
||||
description = S("Axle Power Source"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta2.png^techage_frame_ta2_top.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_axle_clutch.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_source.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_source.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_source.png",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
on_receive_fields = on_receive_fields2,
|
||||
on_rightclick = on_rightclick2,
|
||||
on_timer = node_timer2,
|
||||
after_place_node = after_place_node2,
|
||||
after_dig_node = after_dig_node2,
|
||||
get_generator_data = get_generator_data,
|
||||
})
|
||||
|
||||
minetest.register_node("techage:t4_source", {
|
||||
description = S("Ele Power Source"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_appl_hole_electric.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_source.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_source.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_source.png",
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
on_receive_fields = on_receive_fields3,
|
||||
on_rightclick = on_rightclick3,
|
||||
on_timer = node_timer3,
|
||||
after_place_node = after_place_node3,
|
||||
after_dig_node = after_dig_node3,
|
||||
get_generator_data = get_generator_data,
|
||||
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
|
||||
})
|
||||
|
||||
power.register_nodes({"techage:t2_source"}, Axle, "gen", {"R"})
|
||||
power.register_nodes({"techage:t4_source"}, Cable, "gen", {"R"})
|
||||
|
||||
techage.register_node({"techage:t4_source"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "delivered" then
|
||||
return nvm.provided or 0
|
||||
else
|
||||
return State3:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
control.register_nodes({"techage:t4_source"}, {
|
||||
on_receive = function(pos, tlib2, topic, payload)
|
||||
end,
|
||||
on_request = function(pos, tlib2, topic)
|
||||
if topic == "info" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local meta = M(pos)
|
||||
return {
|
||||
type = S("Ele Power Source"),
|
||||
number = meta:get_string("node_number") or "",
|
||||
running = nvm.running or false,
|
||||
available = PWR_PERF,
|
||||
provided = nvm.provided or 0,
|
||||
termpoint = meta:get_string("termpoint"),
|
||||
}
|
||||
end
|
||||
return false
|
||||
end,
|
||||
}
|
||||
)
|
@ -1,715 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 8x2000 Chest
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local DESCRIPTION = S("TA4 8x2000 Chest")
|
||||
local STACK_SIZE = 2000
|
||||
|
||||
local function gen_stack(inv, idx)
|
||||
inv[idx] = {name = "", count = 0}
|
||||
return inv[idx]
|
||||
end
|
||||
|
||||
local function gen_inv(nvm)
|
||||
nvm.inventory = {}
|
||||
for i = 1,8 do
|
||||
gen_stack(nvm.inventory, i)
|
||||
end
|
||||
return nvm.inventory
|
||||
end
|
||||
|
||||
local function repair_inv(nvm)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
for i = 1,8 do
|
||||
local item = nvm.inventory[i]
|
||||
if not item or type(item) ~= "table"
|
||||
or not item.name or type(item.name) ~= "string" or item.name == ""
|
||||
or not item.count or type(item.count) ~= "number" or item.count < 1
|
||||
then
|
||||
gen_stack(nvm.inventory, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_stack(nvm, idx)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
return nvm.inventory[idx] or gen_stack(nvm.inventory, idx)
|
||||
end
|
||||
|
||||
local function get_count(nvm, idx)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
if idx and idx > 0 then
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].count or 0
|
||||
else
|
||||
local count = 0
|
||||
for _,item in ipairs(nvm.inventory) do
|
||||
count = count + item.count or 0
|
||||
end
|
||||
return count
|
||||
end
|
||||
end
|
||||
|
||||
local function get_itemstring(nvm, idx)
|
||||
if idx and idx > 0 then
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
return nvm.inventory[idx] and nvm.inventory[idx].name or ""
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function inv_empty(nvm)
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function inv_state(nvm)
|
||||
local num = 0
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
if num == 0 then return "empty" end
|
||||
if num == 8 then return "full" end
|
||||
return "loaded"
|
||||
end
|
||||
|
||||
local function inv_state_num(nvm)
|
||||
local num = 0
|
||||
for _,item in ipairs(nvm.inventory or {}) do
|
||||
if item.count and item.count > 0 then
|
||||
num = num + 1
|
||||
end
|
||||
end
|
||||
if num == 0 then return 0 end
|
||||
if num == 8 then return 2 end
|
||||
return 1
|
||||
end
|
||||
|
||||
local function max_stacksize(item_name)
|
||||
-- It is sufficient to use minetest.registered_items as all registration
|
||||
-- functions (node, craftitems, tools) add the definitions there.
|
||||
local ndef = minetest.registered_items[item_name]
|
||||
-- Return 1 as fallback so that slots with unknown items can be emptied.
|
||||
return ndef and ndef.stack_max or 1
|
||||
end
|
||||
|
||||
local function get_stacksize(pos)
|
||||
local size = M(pos):get_int("stacksize")
|
||||
if size == 0 then
|
||||
return STACK_SIZE
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
-- Returns a boolean that indicates if an itemstack and nvmstack can be combined.
|
||||
-- The second return value is a string describing the reason.
|
||||
-- This function guarantees not to modify any of both stacks.
|
||||
local function doesItemStackMatchNvmStack(itemstack, nvmstack)
|
||||
if itemstack:get_count() == 0 or nvmstack.count == 0 then
|
||||
return true, "Empty stack"
|
||||
end
|
||||
if nvmstack.name and nvmstack.name ~= "" and nvmstack.name ~= itemstack:get_name() then
|
||||
return false, "Mismatching names"
|
||||
end
|
||||
|
||||
-- The following seems to be the most reliable approach to compare meta.
|
||||
local nvm_meta = ItemStack():get_meta()
|
||||
nvm_meta:from_table(minetest.deserialize(nvmstack.meta or ""))
|
||||
if not nvm_meta:equals(itemstack:get_meta()) then
|
||||
return false, "Mismatching meta"
|
||||
end
|
||||
if (nvmstack.wear or 0) ~= itemstack:get_wear() then
|
||||
return false, "Mismatching wear"
|
||||
end
|
||||
return true, "Stacks match"
|
||||
end
|
||||
|
||||
|
||||
-- Generic function for adding items to the 8x2000 Chest
|
||||
-- This function guarantees not to modify the itemstack.
|
||||
-- The number of items that were added to the chest is returned.
|
||||
local function add_to_chest(pos, input_stack, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
if input_stack:get_count() == 0 then
|
||||
return 0
|
||||
end
|
||||
if not doesItemStackMatchNvmStack(input_stack, nvm_stack) then
|
||||
return 0
|
||||
end
|
||||
local count = math.min(input_stack:get_count(), get_stacksize(pos) - (nvm_stack.count or 0))
|
||||
if nvm_stack.count == 0 then
|
||||
nvm_stack.name = input_stack:get_name()
|
||||
nvm_stack.meta = minetest.serialize(input_stack:get_meta():to_table())
|
||||
nvm_stack.wear = input_stack:get_wear()
|
||||
end
|
||||
nvm_stack.count = nvm_stack.count + count
|
||||
return count
|
||||
end
|
||||
|
||||
local function stackOrNil(stack)
|
||||
if stack and stack.get_count and stack:get_count() > 0 then
|
||||
return stack
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Generic function for taking items from the 8x2000 Chest
|
||||
-- output_stack is directly modified; but nil can also be supplied.
|
||||
-- The resulting output_stack is returned from the function.
|
||||
-- keep_assignment indicates if the meta information for this function should be considered (manual vs. tubes).
|
||||
local function take_from_chest(pos, idx, output_stack, max_total_count, keep_assignment)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local nvm_stack = get_stack(nvm, idx)
|
||||
output_stack = output_stack or ItemStack()
|
||||
local assignment_count = keep_assignment and M(pos):get_int("assignment") == 1 and 1 or 0
|
||||
local count = math.min(nvm_stack.count - assignment_count, max_stacksize(nvm_stack.name) - output_stack:get_count())
|
||||
if max_total_count then
|
||||
count = math.min(count, max_total_count - output_stack:get_count())
|
||||
end
|
||||
if count < 1 then
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
if not doesItemStackMatchNvmStack(output_stack, nvm_stack) then
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
output_stack:add_item(ItemStack({
|
||||
name = nvm_stack.name,
|
||||
count = count,
|
||||
wear = nvm_stack.wear,
|
||||
}))
|
||||
output_stack:get_meta():from_table(minetest.deserialize(nvm_stack.meta or ""))
|
||||
nvm_stack.count = nvm_stack.count - count
|
||||
if nvm_stack.count == 0 then
|
||||
gen_stack(nvm.inventory or {}, idx)
|
||||
end
|
||||
return stackOrNil(output_stack)
|
||||
end
|
||||
|
||||
-- Function for adding items to the 8x2000 Chest via automation, e.g. pushers
|
||||
local function tube_add_to_chest(pos, input_stack)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
|
||||
for idx = 1,8 do
|
||||
input_stack:take_item(add_to_chest(pos, input_stack, idx))
|
||||
end
|
||||
|
||||
if input_stack:get_count() > 0 then
|
||||
return input_stack -- Not all items were added to chest
|
||||
else
|
||||
return true -- All items were added
|
||||
end
|
||||
end
|
||||
|
||||
-- Function for taking items from the 8x2000 Chest via automation, e.g. pushers
|
||||
local function tube_take_from_chest(pos, item_name, count)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
nvm.inventory = nvm.inventory or {}
|
||||
mem.startpos = mem.startpos or 1
|
||||
local prio = M(pos):get_int("priority") == 1
|
||||
local startpos = prio and 8 or mem.startpos
|
||||
local endpos = prio and 1 or mem.startpos + 8
|
||||
local step = prio and -1 or 1
|
||||
local itemstack = ItemStack()
|
||||
for idx = startpos,endpos,step do
|
||||
idx = ((idx - 1) % 8) + 1
|
||||
local nvmstack = get_stack(nvm, idx)
|
||||
if not item_name or item_name == nvmstack.name then
|
||||
take_from_chest(pos, idx, itemstack, count - itemstack:get_count(), true)
|
||||
if itemstack:get_count() == count then
|
||||
mem.startpos = idx + 1
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
mem.startpos = idx + 1
|
||||
end
|
||||
return stackOrNil(itemstack)
|
||||
end
|
||||
|
||||
-- Function for manually adding items to the 8x2000 Chest via the formspec
|
||||
local function inv_add_to_chest(pos, idx)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
local count = add_to_chest(pos, inv_stack, idx)
|
||||
inv_stack:set_count(inv_stack:get_count() - count)
|
||||
inv:set_stack("main", idx, inv_stack)
|
||||
end
|
||||
|
||||
-- Function for manually taking items from the 8x2000 Chest via the formspec
|
||||
local function inv_take_from_chest(pos, idx)
|
||||
local inv = M(pos):get_inventory()
|
||||
local inv_stack = inv:get_stack("main", idx)
|
||||
if inv_stack:get_count() > 0 then
|
||||
return
|
||||
end
|
||||
local output_stack = take_from_chest(pos, idx)
|
||||
if output_stack then
|
||||
inv:set_stack("main", idx, output_stack)
|
||||
end
|
||||
end
|
||||
|
||||
local function formspec_container(x, y, nvm, inv)
|
||||
local tbl = {"container["..x..","..y.."]"}
|
||||
for i = 1,8 do
|
||||
local xpos = i - 1
|
||||
tbl[#tbl+1] = "box["..(xpos - 0.03)..",0;0.86,0.9;#808080]"
|
||||
local stack = get_stack(nvm, i)
|
||||
if stack.name ~= "" then
|
||||
local itemstack = ItemStack({
|
||||
name = stack.name,
|
||||
count = stack.count,
|
||||
wear = stack.wear,
|
||||
})
|
||||
local stack_meta_table = (minetest.deserialize(stack.meta) or {}).fields or {}
|
||||
for _, key in ipairs({"description", "short_description", "color", "palette_index"}) do
|
||||
if stack_meta_table[key] then
|
||||
itemstack:get_meta():set_string(key, stack_meta_table[key])
|
||||
end
|
||||
end
|
||||
local itemname = itemstack:to_string()
|
||||
--tbl[#tbl+1] = "item_image["..xpos..",1;1,1;"..itemname.."]"
|
||||
tbl[#tbl+1] = techage.item_image(xpos, 0, itemname, stack.count)
|
||||
end
|
||||
if inv:get_stack("main", i):get_count() == 0 then
|
||||
tbl[#tbl+1] = "image_button["..xpos..",1;1,1;techage_form_get_arrow.png;get"..i..";]"
|
||||
else
|
||||
tbl[#tbl+1] = "image_button["..xpos..",1;1,1;techage_form_add_arrow.png;add"..i..";]"
|
||||
end
|
||||
end
|
||||
tbl[#tbl+1] = "list[context;main;0,2;8,1;]"
|
||||
tbl[#tbl+1] = "container_end[]"
|
||||
return table.concat(tbl, "")
|
||||
end
|
||||
|
||||
local function formspec(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local size = get_stacksize(pos)
|
||||
local assignment = M(pos):get_int("assignment") == 1 and "true" or "false"
|
||||
local priority = M(pos):get_int("priority") == 1 and "true" or "false"
|
||||
return "size[8,8.3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
formspec_container(0, 0, nvm, inv)..
|
||||
"button[0,3.5;3,1;unlock;"..S("Unlock").."]"..
|
||||
"tooltip[0,3.5;3,1;"..S("Unlock connected chest\nif all slots are below 2000")..";#0C3D32;#FFFFFF]"..
|
||||
"label[0,3;"..S("Size")..": 8x"..size.."]"..
|
||||
"checkbox[4,3;assignment;"..S("keep assignment")..";"..assignment.."]"..
|
||||
"tooltip[4,3;2,0.6;"..S("Never completely empty the slots\nwith the pusher to keep the item assignment")..";#0C3D32;#FFFFFF]"..
|
||||
"checkbox[4,3.6;priority;"..S("right to left")..";"..priority.."]"..
|
||||
"tooltip[4,3.6;2,0.6;"..S("Empty the slots always \nfrom right to left")..";#0C3D32;#FFFFFF]"..
|
||||
"list[current_player;main;0,4.6;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function count_number_of_chests(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local param2 = node.param2
|
||||
local cnt = 1
|
||||
while cnt < 50 do
|
||||
node = techage.get_node_lvm(pos1)
|
||||
if node.name ~= "techage:ta4_chest_dummy" then
|
||||
break
|
||||
end
|
||||
local meta = M(pos1)
|
||||
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
|
||||
break
|
||||
end
|
||||
pos1 = tubelib2.get_pos(pos1, dir)
|
||||
cnt = cnt + 1
|
||||
end
|
||||
M(pos):set_int("stacksize", STACK_SIZE * cnt)
|
||||
end
|
||||
|
||||
local function dummy_chest_behind(pos, node)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
node = techage.get_node_lvm(pos1)
|
||||
return node.name == "techage:ta4_chest_dummy"
|
||||
end
|
||||
|
||||
local function part_of_a_chain(pos, node)
|
||||
local dir = techage.side_to_outdir("F", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
node = techage.get_node_lvm(pos1)
|
||||
return node.name == "techage:ta4_chest_dummy" or node.name == "techage:ta4_chest"
|
||||
end
|
||||
|
||||
local function search_chest_in_front(pos, node)
|
||||
local dir = techage.side_to_outdir("F", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local param2 = node.param2
|
||||
local cnt = 1
|
||||
while cnt < 50 do
|
||||
node = techage.get_node_lvm(pos1)
|
||||
if node.name ~= "techage:ta4_chest_dummy" then
|
||||
break
|
||||
end
|
||||
local meta = M(pos1)
|
||||
if meta:contains("param2") and meta:get_int("param2") ~= param2 then
|
||||
break
|
||||
end
|
||||
pos1 = tubelib2.get_pos(pos1, dir)
|
||||
cnt = cnt + 1
|
||||
end
|
||||
if node.name == "techage:ta4_chest" and node.param2 == param2 then
|
||||
minetest.after(1, count_number_of_chests, pos1)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.front_chest_pos = pos1
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function get_front_chest_pos(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.front_chest_pos then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if search_chest_in_front(pos, node) then
|
||||
return nvm.front_chest_pos
|
||||
end
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
local function convert_to_chest_again(pos, node, player)
|
||||
local dir = techage.side_to_outdir("B", node.param2)
|
||||
local pos1 = tubelib2.get_pos(pos, dir)
|
||||
local node1 = techage.get_node_lvm(pos1)
|
||||
if minetest.is_protected(pos1, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
if node1.name == "techage:ta4_chest_dummy" then
|
||||
node1.name = "techage:ta4_chest"
|
||||
minetest.swap_node(pos1, node1)
|
||||
--M(pos1):set_int("disabled", 1)
|
||||
local nvm = techage.get_nvm(pos1)
|
||||
gen_inv(nvm)
|
||||
local number = techage.add_node(pos1, "techage:ta4_chest")
|
||||
M(pos1):set_string("owner", player:get_player_name())
|
||||
M(pos1):set_string("formspec", formspec(pos1))
|
||||
M(pos1):set_string("infotext", DESCRIPTION.." "..number)
|
||||
end
|
||||
end
|
||||
|
||||
local function unlock_chests(pos, player)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
for idx = 1,8 do
|
||||
if get_count(nvm, idx) > STACK_SIZE then return end
|
||||
end
|
||||
local node = techage.get_node_lvm(pos)
|
||||
convert_to_chest_again(pos, node, player)
|
||||
M(pos):set_int("stacksize", STACK_SIZE)
|
||||
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
|
||||
return stack:get_count()
|
||||
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
|
||||
return stack:get_count()
|
||||
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
|
||||
return count
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, player)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if M(pos):get_int("disabled") ~= 1 then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
repair_inv(nvm)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1,8 do
|
||||
if fields["get"..i] ~= nil then
|
||||
inv_take_from_chest(pos, i)
|
||||
break
|
||||
elseif fields["add"..i] ~= nil then
|
||||
inv_add_to_chest(pos, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
if fields.unlock then
|
||||
unlock_chests(pos, player)
|
||||
end
|
||||
if fields.assignment then
|
||||
M(pos):set_int("assignment", fields.assignment == "true" and 1 or 0)
|
||||
end
|
||||
if fields.priority then
|
||||
M(pos):set_int("priority", fields.priority == "true" and 1 or 0)
|
||||
end
|
||||
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
|
||||
local function can_dig(pos, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return inv:is_empty("main") and inv_empty(nvm)
|
||||
end
|
||||
|
||||
local function on_rotate(pos, node, user, mode, new_param2)
|
||||
if get_stacksize(pos) == STACK_SIZE then
|
||||
return screwdriver.rotate_simple(pos, node, user, mode, new_param2)
|
||||
else
|
||||
return screwdriver.disallow(pos, node, user, mode, new_param2)
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
convert_to_chest_again(pos, oldnode, digger)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_chest", {
|
||||
description = DESCRIPTION,
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png^techage_appl_warehouse.png",
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 8)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local node = minetest.get_node(pos)
|
||||
if dummy_chest_behind(pos, node) then
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
if search_chest_in_front(pos, node) then
|
||||
node.name = "techage:ta4_chest_dummy"
|
||||
minetest.swap_node(pos, node)
|
||||
M(pos):set_int("param2", node.param2)
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
gen_inv(nvm)
|
||||
local number = techage.add_node(pos, "techage:ta4_chest")
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
M(pos):set_string("infotext", DESCRIPTION.." "..number)
|
||||
end
|
||||
end,
|
||||
|
||||
techage_set_numbers = function(pos, numbers, player_name)
|
||||
return techage.logic.set_numbers(pos, numbers, player_name, DESCRIPTION)
|
||||
end,
|
||||
|
||||
on_rotate = on_rotate,
|
||||
on_rightclick = on_rightclick,
|
||||
on_receive_fields = on_receive_fields,
|
||||
can_dig = can_dig,
|
||||
after_dig_node = after_dig_node,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
on_metadata_inventory_put = on_metadata_inventory_put,
|
||||
on_metadata_inventory_move = on_metadata_inventory_move,
|
||||
on_metadata_inventory_take = on_metadata_inventory_take,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_chest_dummy", {
|
||||
description = DESCRIPTION,
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_back_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_chest_front_ta4.png^techage_appl_warehouse.png",
|
||||
},
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
end,
|
||||
paramtype2 = "facedir",
|
||||
diggable = false,
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
|
||||
techage.register_node({"techage:ta4_chest"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local res = tube_take_from_chest(pos, item_name, num)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local res = tube_add_to_chest(pos, stack)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local res = tube_add_to_chest(pos, stack)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "count" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return get_count(nvm, tonumber(payload or 0) or 0)
|
||||
elseif topic == "itemstring" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return get_itemstring(nvm, tonumber(payload or 0) or 0)
|
||||
elseif topic == "storesize" then
|
||||
return get_stacksize(pos)
|
||||
elseif topic == "state" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return inv_state(nvm)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 140 and payload[1] == 1 then -- Inventory Item Count
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {get_count(nvm, tonumber(payload[2] or 0) or 0)}
|
||||
elseif topic == 140 and payload[1] == 2 then -- Inventory Item Name
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, get_itemstring(nvm, tonumber(payload[2] or 0) or 0)
|
||||
elseif topic == 140 and payload[1] == 3 then -- storesize
|
||||
return 0, {get_stacksize(pos)}
|
||||
elseif topic == 131 then -- Chest State
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return 0, {inv_state_num(nvm)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_chest_dummy"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_take_from_chest(fc_pos, item_name, num)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local fc_pos = get_front_chest_pos(pos)
|
||||
local res = tube_add_to_chest(fc_pos, stack)
|
||||
if techage.is_activeformspec(fc_pos) then
|
||||
M(fc_pos):set_string("formspec", formspec(fc_pos))
|
||||
end
|
||||
return res
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Repair Dummy Chests",
|
||||
name = "techage:chest_dummy",
|
||||
nodenames = {"techage:ta4_chest_dummy"},
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
if not part_of_a_chain(pos, node) then
|
||||
minetest.swap_node(pos, {name = "techage:ta4_chest", param2 = node.param2})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:ta4_chest",
|
||||
recipe = {"techage:chest_ta4"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:chest_ta4",
|
||||
recipe = {"techage:ta4_chest"}
|
||||
})
|
@ -1,331 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Injector
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
local tooltip = S("Switch to pull mode \nto pull items out of inventory slots \naccording the injector configuration")
|
||||
local Tube = techage.Tube
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 3
|
||||
local CYCLE_TIME = 4
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local pull_mode = dump(nvm.pull_mode or false)
|
||||
return "size[8,7.2]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize("#000000", S("Injector")).."]"..
|
||||
techage.question_mark_help(8, S("Configure up to 8 items \nto be pushed by the injector"))..
|
||||
"list[context;filter;0,0.8;8,1;]"..
|
||||
"image_button[2,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"checkbox[3.5,1.9;pull_mode;"..S("pull mode")..";"..pull_mode.."]"..
|
||||
"tooltip[3.5,1.9;2,0.8;"..tooltip..";#0C3D32;#FFFFFF]"..
|
||||
"list[current_player;main;0,3.5;8,4;]"..
|
||||
"listring[context;filter]"..
|
||||
"listring[current_player;main]"
|
||||
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 nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
local cdr = CRD(pos)
|
||||
if list[index]:get_count() < cdr.num_items then
|
||||
local num = math.min(cdr.num_items - list[index]:get_count(), stack:get_count()) + list[index]:get_count()
|
||||
stack:set_count(num)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
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
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) ~= techage.STOPPED then
|
||||
return 0
|
||||
end
|
||||
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function pull_items(pos, out_dir, idx, name, num)
|
||||
local inv, listname = techage.get_inv_access(pos, out_dir, "pull")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
if stack and not stack:is_empty() and stack:get_name() == name then
|
||||
local taken = stack:take_item(num)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
return (taken:get_count() > 0) and taken or nil
|
||||
end
|
||||
else
|
||||
local taken = inv:remove_item(listname, {name = name, count = num})
|
||||
return (taken:get_count() > 0) and taken or nil
|
||||
end
|
||||
else
|
||||
return techage.pull_items(pos, out_dir, num, name)
|
||||
end
|
||||
end
|
||||
|
||||
local function push_items(pos, out_dir, idx, items)
|
||||
local inv, listname, callafter, dpos = techage.get_inv_access(pos, out_dir, "push")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
if stack:item_fits(items) then
|
||||
stack:add_item(items)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
if callafter then
|
||||
callafter(dpos)
|
||||
end
|
||||
return true
|
||||
end
|
||||
else
|
||||
if inv:room_for_item(listname, items) then
|
||||
inv:add_item(listname, items)
|
||||
if callafter then
|
||||
callafter(dpos)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
else
|
||||
local taken = items:get_count()
|
||||
local leftover = techage.push_items(pos, out_dir, items, idx)
|
||||
if not leftover or leftover == false then
|
||||
return false -- No items placed
|
||||
elseif leftover ~= true then
|
||||
-- One or more items placed?
|
||||
if leftover:get_count() < taken then
|
||||
-- place the rest back
|
||||
local pull_dir = M(pos):get_int("pull_dir")
|
||||
techage.unpull_items(pos, pull_dir, leftover)
|
||||
return true -- Some items placed
|
||||
end
|
||||
return false -- No items placed
|
||||
end
|
||||
return true -- All items placed
|
||||
end
|
||||
end
|
||||
|
||||
local function unpull_items(pos, out_dir, idx, items)
|
||||
local inv, listname = techage.get_inv_access(pos, out_dir, "unpull")
|
||||
if inv and listname then
|
||||
if idx and idx ~= 0 then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
stack:add_item(items)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
else
|
||||
inv:add_item(listname, items)
|
||||
end
|
||||
else
|
||||
techage.unpull_items(pos, out_dir, items)
|
||||
end
|
||||
end
|
||||
|
||||
local function pushing(pos, crd, meta, nvm)
|
||||
local pull_dir = meta:get_int("pull_dir")
|
||||
local push_dir = meta:get_int("push_dir")
|
||||
local inv = M(pos):get_inventory()
|
||||
local filter = inv:get_list("filter")
|
||||
local pushed = false
|
||||
local pulled = false
|
||||
|
||||
for idx, item in ipairs(filter) do
|
||||
local name = item:get_name()
|
||||
local num = math.min(item:get_count(), crd.num_items)
|
||||
if name ~= "" and num > 0 then
|
||||
local items = pull_items(pos, pull_dir, nvm.pull_mode and idx, name, num)
|
||||
if items ~= nil then
|
||||
pulled = true
|
||||
if push_items(pos, push_dir, not nvm.pull_mode and idx, items) then
|
||||
pushed = true
|
||||
else -- place item back
|
||||
unpull_items(pos, pull_dir, nvm.pull_mode and idx, items)
|
||||
pulled = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not pulled then
|
||||
crd.State:idle(pos, nvm)
|
||||
elseif not pushed then
|
||||
crd.State:blocked(pos, nvm)
|
||||
else
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
pushing(pos, crd, M(pos), nvm)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if fields.pull_mode then
|
||||
nvm.pull_mode = fields.pull_mode == "true"
|
||||
end
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
tiles.pas = {
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
"techage_appl_pusher.png^[transformR180]^techage_frame_ta#.png^techage_appl_injector.png",
|
||||
"techage_appl_pusher.png^techage_frame_ta#.png^techage_appl_injector.png",
|
||||
}
|
||||
tiles.act = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_arrow.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png",
|
||||
"techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png",
|
||||
{
|
||||
name = "techage_appl_pusher14.png^[transformR180]^techage_frame14_ta#.png^techage_appl_injector14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_appl_pusher14.png^techage_frame14_ta#.png^techage_appl_injector14.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
-- push item through the injector in opposit direction
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
return in_dir == M(pos):get_int("pull_dir") and techage.safe_push_items(pos, in_dir, stack)
|
||||
end,
|
||||
is_pusher = true, -- is a pulling/pushing node
|
||||
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
on_node_load = function(pos)
|
||||
CRD(pos).State:on_node_load(pos)
|
||||
end,
|
||||
}
|
||||
|
||||
local _, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("injector", S("Injector"), tiles, {
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
quick_start = node_timer,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", node.param2))
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('filter', 8)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end,
|
||||
ta_rotate_node = function(pos, node, new_param2)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if CRD(pos).State:get_state(nvm) == techage.STOPPED then
|
||||
Tube:after_dig_node(pos)
|
||||
minetest.swap_node(pos, {name = node.name, param2 = new_param2})
|
||||
Tube:after_place_node(pos)
|
||||
local meta = M(pos)
|
||||
meta:set_int("pull_dir", techage.side_to_outdir("L", new_param2))
|
||||
meta:set_int("push_dir", techage.side_to_outdir("R", new_param2))
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
allow_metadata_inventory_move = function() return 0 end,
|
||||
on_receive_fields = on_receive_fields,
|
||||
node_timer = node_timer,
|
||||
on_rotate = screwdriver.disallow,
|
||||
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
num_items = {0,0,1,4},
|
||||
}, {false, false, true, true})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"", "default:steel_ingot", ""},
|
||||
{"", "techage:ta3_pusher_pas", ""},
|
||||
{"", "basic_materials:ic", ""},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta4,
|
||||
recipe = {
|
||||
{"", "techage:aluminum", ""},
|
||||
{"", "techage:ta4_pusher_pas", ""},
|
||||
{"", "basic_materials:ic", ""},
|
||||
},
|
||||
})
|
@ -1,248 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 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 = 15
|
||||
|
||||
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_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]"
|
||||
elseif hyperloop.is_client(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) .. "]" ..
|
||||
"label[0.2,2;Inventory access on this node is disabled\ndue to minetest engine issues!]" ..
|
||||
"list[current_player;main;0,5.3;8,4;]"
|
||||
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
|
||||
if techage.hyperloop.is_client(pos) then
|
||||
return 0
|
||||
end
|
||||
shared_inv.before_inv_access(pos, listname)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if inv and 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
|
||||
if techage.hyperloop.is_client(pos) then
|
||||
return 0
|
||||
end
|
||||
shared_inv.before_inv_access(pos, listname)
|
||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||
if inv and 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
|
||||
if techage.hyperloop.is_client(pos) 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)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
return meta:get_inventory(), "main"
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.get_items(pos, inv, "main", num)
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
if techage.hyperloop.is_paired(pos) then
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
pos = remote_pos(pos)
|
||||
if pos then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "state" then
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return techage.get_inv_state(inv, "main")
|
||||
end
|
||||
end
|
||||
return "error"
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then -- Chest State
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
local inv = meta:get_inventory()
|
||||
if inv then
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
end
|
||||
end
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:ta5_hl_chest",
|
||||
recipe = {"techage:chest_ta4", "techage:ta5_aichip"}
|
||||
})
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
if not minetest.global_exists("hyperloop") then
|
||||
minetest.clear_craft({output = "techage:ta5_hl_chest"})
|
||||
end
|
||||
end)
|
@ -1,242 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Assemble routines
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
techage.assemble = {}
|
||||
|
||||
local Face2Dir = {[0]=
|
||||
{x=0, y=0, z=1},
|
||||
{x=1, y=0, z=0},
|
||||
{x=0, y=0, z=-1},
|
||||
{x=-1, y=0, z=0},
|
||||
{x=0, y=-1, z=0},
|
||||
{x=0, y=1, z=0}
|
||||
}
|
||||
|
||||
-- Determine the destination position based on the base position,
|
||||
-- param2, and a route table like : {0,3}
|
||||
-- 0 = forward, 1 = right, 2 = backward, 3 = left
|
||||
local function dest_pos(pos, param2, route, y_offs)
|
||||
local p2 = param2
|
||||
local pos1 = {x=pos.x, y=pos.y+y_offs, z=pos.z}
|
||||
for _,dir in ipairs(route) do
|
||||
p2 = (param2 + dir) % 4
|
||||
pos1 = vector.add(pos1, Face2Dir[p2])
|
||||
end
|
||||
return pos1, p2
|
||||
end
|
||||
|
||||
|
||||
-- timer based function
|
||||
local function build(pos, param2, AssemblyPlan, 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)
|
||||
minetest.add_node(pos1, {name=node_name, param2=(param2 + fd_offs) % 4})
|
||||
minetest.after(0.5, build, pos, param2, AssemblyPlan, idx+1)
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.assemble_locked = false
|
||||
end
|
||||
end
|
||||
|
||||
-- timer based function
|
||||
local function remove(pos, param2, AssemblyPlan, idx)
|
||||
local item = AssemblyPlan[idx]
|
||||
if item ~= nil then
|
||||
local y, path = item[1], item[2]
|
||||
local pos1 = dest_pos(pos, param2, path, y)
|
||||
minetest.remove_node(pos1)
|
||||
minetest.after(0.5, remove, pos, param2, AssemblyPlan, idx-1)
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.assemble_locked = false
|
||||
end
|
||||
end
|
||||
|
||||
local function check_space(pos, param2, AssemblyPlan, player_name)
|
||||
for _,item in ipairs(AssemblyPlan) do
|
||||
local y, path, node_name = item[1], item[2], item[4]
|
||||
local pos1 = dest_pos(pos, param2, path, y)
|
||||
if minetest.is_protected(pos1, player_name) then
|
||||
minetest.chat_send_player(player_name, S("[TA] Area is protected!"))
|
||||
return false
|
||||
end
|
||||
|
||||
local node = techage.get_node_lvm(pos1)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if not ndef or not ndef.buildable_to and node.name ~= node_name then
|
||||
minetest.chat_send_player(player_name, S("[TA] Not enough space!"))
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- Two important flags:
|
||||
-- 1) nvm.assemble_locked is true while the object is being assembled/disassembled
|
||||
-- 2) nvm.assemble_build is true if the object is assembled
|
||||
function techage.assemble.build(pos, 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)
|
||||
if check_space(pos, node.param2, AssemblyPlan, player_name) then
|
||||
nvm.assemble_locked = true
|
||||
build(pos, node.param2, AssemblyPlan, 1)
|
||||
nvm.assemble_build = true
|
||||
end
|
||||
end
|
||||
|
||||
function techage.assemble.remove(pos, 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(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
|
||||
local meta = M(pos1):to_table()
|
||||
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, node, meta, 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
|
@ -1,150 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Boiler common functions
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local HEAT_STEP = 10
|
||||
local MAX_WATER = 10
|
||||
local BLOCKING_TIME = 0.3 -- 300ms
|
||||
|
||||
techage.boiler = {}
|
||||
|
||||
local IsWater = {
|
||||
["bucket:bucket_river_water"] = "bucket:bucket_empty",
|
||||
}
|
||||
|
||||
local IsBucket = {}
|
||||
|
||||
local function node_description(name)
|
||||
name = string.split(name, " ")[1]
|
||||
local ndef = minetest.registered_nodes[name] or minetest.registered_items[name] or minetest.registered_craftitems[name]
|
||||
if ndef and ndef.description then
|
||||
return minetest.formspec_escape(ndef.description)
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
local function item_image(x, y, itemname)
|
||||
return "box["..x..","..y..";0.85,0.9;#808080]"..
|
||||
"item_image["..x..","..y..";1,1;"..itemname.."]"
|
||||
end
|
||||
|
||||
function techage.boiler.formspec(pos, nvm)
|
||||
local title = S("Water Boiler")
|
||||
local temp = nvm.temperature or 20
|
||||
local ratio = nvm.power_ratio or 0
|
||||
local tooltip = S("To add water punch\nthe boiler\nwith a water bucket")
|
||||
return "size[5,3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1.5,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
item_image(1, 1.5, "default:water_source "..(nvm.num_water or 0))..
|
||||
"tooltip[1,1.5;1,1;"..tooltip..";#0C3D32;#FFFFFF]"..
|
||||
"image[3,1.0;1,2;techage_form_temp_bg.png^[lowpart:"..
|
||||
temp..":techage_form_temp_fg.png]"..
|
||||
"tooltip[3,1;1,2;"..S("water temperature")..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
function techage.boiler.water_temperature(pos, nvm)
|
||||
nvm.temperature = nvm.temperature or 20
|
||||
nvm.num_water = nvm.num_water or 0
|
||||
nvm.water_level = nvm.water_level or 0
|
||||
if nvm.fire_trigger then
|
||||
nvm.temperature = math.min(nvm.temperature + HEAT_STEP, 100)
|
||||
else
|
||||
nvm.temperature = math.max(nvm.temperature - HEAT_STEP, 20)
|
||||
end
|
||||
nvm.fire_trigger = false
|
||||
|
||||
if nvm.water_level == 0 then
|
||||
if nvm.num_water > 0 then
|
||||
nvm.num_water = nvm.num_water - 1
|
||||
nvm.water_level = 100
|
||||
else
|
||||
nvm.temperature = 20
|
||||
end
|
||||
end
|
||||
return nvm.temperature
|
||||
end
|
||||
|
||||
function techage.boiler.on_rightclick(pos, node, clicker)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
|
||||
end
|
||||
|
||||
function techage.boiler.can_dig(pos, player)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.num_water = nvm.num_water or 0
|
||||
return nvm.num_water == 0
|
||||
end
|
||||
|
||||
local function space_in_inventory(wielded_item, item_count, puncher)
|
||||
-- check if holding more than 1 empty container
|
||||
if item_count > 1 then
|
||||
local inv = puncher:get_inventory()
|
||||
local item = ItemStack({name=wielded_item, count = item_count - 1})
|
||||
if inv:room_for_item("main", item) then
|
||||
inv:add_item("main", item)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function techage.boiler.on_punch(pos, node, puncher, pointed_thing)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.blocking_time = mem.blocking_time or 0
|
||||
if mem.blocking_time > techage.SystemTime then
|
||||
return
|
||||
end
|
||||
|
||||
nvm.num_water = nvm.num_water or 0
|
||||
local wielded_item = puncher:get_wielded_item():get_name()
|
||||
local item_count = puncher:get_wielded_item():get_count()
|
||||
if IsWater[wielded_item] and nvm.num_water < MAX_WATER then
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
nvm.num_water = nvm.num_water + 1
|
||||
puncher:set_wielded_item(ItemStack(IsWater[wielded_item]))
|
||||
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
|
||||
elseif IsBucket[wielded_item] and nvm.num_water > 0 then
|
||||
if item_count > 1 then
|
||||
local inv = puncher:get_inventory()
|
||||
local item = ItemStack(IsBucket[wielded_item])
|
||||
if inv:room_for_item("main", item) then
|
||||
inv:add_item("main", item)
|
||||
puncher:set_wielded_item({name=wielded_item, count = item_count - 1})
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
nvm.num_water = nvm.num_water - 1
|
||||
end
|
||||
else
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
nvm.num_water = nvm.num_water - 1
|
||||
puncher:set_wielded_item(ItemStack(IsBucket[wielded_item]))
|
||||
end
|
||||
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
function techage.register_water_bucket(empty_bucket, full_bucket)
|
||||
IsWater[full_bucket] = empty_bucket
|
||||
IsBucket[empty_bucket] = full_bucket
|
||||
end
|
@ -1,691 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Basis functions for inter-node communication
|
||||
|
||||
]]--
|
||||
|
||||
--- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
--local P = minetest.string_to_pos
|
||||
--local M = minetest.get_meta
|
||||
local has_mesecons = minetest.global_exists("mesecon")
|
||||
|
||||
local NodeInfoCache = {}
|
||||
local NumbersToBeRecycled = {}
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local techage_use_sqlite = minetest.settings:get_bool('techage_use_sqlite', false)
|
||||
|
||||
-- Localize functions to avoid table lookups (better performance)
|
||||
local string_split = string.split
|
||||
local NodeDef = techage.NodeDef
|
||||
local Tube = techage.Tube
|
||||
local is_cart_available = minecart.is_nodecart_available
|
||||
local techage_counting_hit = techage.counting_hit
|
||||
local tubelib2_side_to_dir = tubelib2.side_to_dir
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Database
|
||||
-------------------------------------------------------------------
|
||||
local backend
|
||||
if techage_use_sqlite then
|
||||
backend = dofile(MP .. "/basis/numbers_sqlite.lua")
|
||||
else
|
||||
backend = dofile(MP .. "/basis/numbers_storage.lua")
|
||||
end
|
||||
|
||||
local function update_nodeinfo(number)
|
||||
local pos = backend.get_nodepos(number)
|
||||
if pos then
|
||||
NodeInfoCache[number] = {pos = pos, name = techage.get_node_lvm(pos).name}
|
||||
return NodeInfoCache[number]
|
||||
end
|
||||
end
|
||||
|
||||
local function delete_nodeinfo_entry(number)
|
||||
if number and NodeInfoCache[number] then
|
||||
number = next(NodeInfoCache, number)
|
||||
if number then
|
||||
NodeInfoCache[number] = nil
|
||||
end
|
||||
else
|
||||
number = next(NodeInfoCache, nil)
|
||||
end
|
||||
return number
|
||||
end
|
||||
|
||||
-- Keep the cache size small by deleting entries randomly
|
||||
local function keep_small(number)
|
||||
number = delete_nodeinfo_entry(number)
|
||||
minetest.after(10, keep_small, number)
|
||||
end
|
||||
|
||||
keep_small()
|
||||
|
||||
minetest.after(2, backend.delete_invalid_entries, NodeDef)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Local helper functions
|
||||
-------------------------------------------------------------------
|
||||
local function in_list(list, x)
|
||||
for _, v in ipairs(list) do
|
||||
if v == x then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Determine position related node number for addressing purposes
|
||||
local function get_number(pos, new)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:contains("node_number") then
|
||||
return meta:get_string("node_number")
|
||||
end
|
||||
-- generate new number
|
||||
if new then
|
||||
local num = backend.add_nodepos(pos)
|
||||
meta:set_string("node_number", num)
|
||||
return num
|
||||
end
|
||||
end
|
||||
|
||||
local function not_protected(pos, placer_name, clicker_name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta then
|
||||
if placer_name and not minetest.is_protected(pos, placer_name) then
|
||||
if clicker_name == nil or placer_name == clicker_name then
|
||||
return true
|
||||
end
|
||||
if not minetest.is_protected(pos, clicker_name) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function register_lbm(name, nodenames)
|
||||
minetest.register_lbm({
|
||||
label = "[TechAge] Node update",
|
||||
name = name.."update",
|
||||
nodenames = nodenames,
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
if NodeDef[node.name] and NodeDef[node.name].on_node_load then
|
||||
NodeDef[node.name].on_node_load(pos, node)
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6}
|
||||
|
||||
local function side_to_dir(side, param2)
|
||||
return tubelib2_side_to_dir(side, param2)
|
||||
end
|
||||
|
||||
techage.side_to_outdir = side_to_dir
|
||||
|
||||
function techage.side_to_indir(side, param2)
|
||||
return tubelib2.Turn180Deg[side_to_dir(side, param2)]
|
||||
end
|
||||
|
||||
local function get_next_node(pos, out_dir)
|
||||
local res, npos, node = Tube:compatible_node(pos, out_dir)
|
||||
local in_dir = tubelib2.Turn180Deg[out_dir]
|
||||
return res, npos, in_dir, node.name
|
||||
end
|
||||
|
||||
local function get_dest_node(pos, out_dir)
|
||||
local spos, in_dir = Tube:get_connected_node_pos(pos, out_dir)
|
||||
local _,node = Tube:get_node(spos)
|
||||
return spos, in_dir, node.name
|
||||
end
|
||||
|
||||
local function item_handling_node(name)
|
||||
local node_def = name and NodeDef[name]
|
||||
if node_def then
|
||||
return node_def.on_pull_item or node_def.on_push_item or node_def.is_pusher
|
||||
end
|
||||
end
|
||||
|
||||
local function is_air_like(name)
|
||||
local ndef = minetest.registered_nodes[name]
|
||||
if ndef and ndef.buildable_to then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
techage.SystemTime = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
techage.SystemTime = techage.SystemTime + dtime
|
||||
end)
|
||||
|
||||
-- used by TA1 hammer: dug_node[player_name] = pos
|
||||
techage.dug_node = {}
|
||||
minetest.register_on_dignode(function(pos, oldnode, digger)
|
||||
if not digger then return end
|
||||
-- store the position of the dug block for tools like the TA1 hammer
|
||||
techage.dug_node[digger:get_player_name()] = pos
|
||||
end)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API helper functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- Check if both strings are the same or one string starts with the other string.
|
||||
function techage.string_compare(s1, s2)
|
||||
if s1 and s2 then
|
||||
local minLength = math.min(#s1, #s2)
|
||||
return string.sub(s1, 1, minLength) == string.sub(s2, 1, minLength)
|
||||
end
|
||||
end
|
||||
|
||||
-- Function returns { pos, name } for the node referenced by number
|
||||
function techage.get_node_info(dest_num)
|
||||
return NodeInfoCache[dest_num] or update_nodeinfo(dest_num)
|
||||
end
|
||||
|
||||
-- Function returns the node number from the given position or
|
||||
-- nil, if no node number for this position is assigned.
|
||||
function techage.get_node_number(pos)
|
||||
return get_number(pos)
|
||||
end
|
||||
|
||||
function techage.get_pos(pos, side)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
local dir = nil
|
||||
if node.name ~= "air" and node.name ~= "ignore" then
|
||||
dir = side_to_dir(side, node.param2)
|
||||
end
|
||||
return tubelib2.get_pos(pos, dir)
|
||||
end
|
||||
|
||||
-- Function is used for available nodes with lost numbers, only.
|
||||
function techage.get_new_number(pos, name)
|
||||
-- store position
|
||||
return get_number(pos, true)
|
||||
end
|
||||
|
||||
-- extract ident and value from strings like "ident=value"
|
||||
function techage.ident_value(s)
|
||||
local ident, value = unpack(string.split(s, "=", true, 1))
|
||||
return (ident or ""):trim(), (value or ""):trim()
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Node construction/destruction functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- Add node to the techage lists.
|
||||
-- Function determines and returns the node position number,
|
||||
-- needed for message communication.
|
||||
-- If TA2 node, return '-' instead of a real number, because
|
||||
-- TA2 nodes should not support number based commands.
|
||||
function techage.add_node(pos, name, is_ta2)
|
||||
if item_handling_node(name) then
|
||||
Tube:after_place_node(pos)
|
||||
end
|
||||
if is_ta2 then
|
||||
return "-"
|
||||
end
|
||||
local key = minetest.hash_node_position(pos)
|
||||
local num = NumbersToBeRecycled[key]
|
||||
if num then
|
||||
NodeInfoCache[num] = nil
|
||||
backend.set_nodepos(num, pos)
|
||||
NumbersToBeRecycled[key] = nil
|
||||
return num
|
||||
end
|
||||
return get_number(pos, true)
|
||||
end
|
||||
|
||||
-- Function removes the node from the techage lists.
|
||||
function techage.remove_node(pos, oldnode, oldmetadata)
|
||||
local number = oldmetadata and oldmetadata.fields and (oldmetadata.fields.node_number or oldmetadata.fields.number)
|
||||
number = number or get_number(pos)
|
||||
if number and tonumber(number) then
|
||||
local key = minetest.hash_node_position(pos)
|
||||
NumbersToBeRecycled[key] = number
|
||||
NodeInfoCache[number] = nil
|
||||
end
|
||||
if oldnode and item_handling_node(oldnode.name) then
|
||||
Tube:after_dig_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Repairs the node number after it was erased by `backend.delete_invalid_entries`
|
||||
function techage.repair_number(pos)
|
||||
local number = techage.get_node_number(pos)
|
||||
if number then
|
||||
backend.set_nodepos(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
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Used by the assembly tool
|
||||
-------------------------------------------------------------------
|
||||
function techage.pre_add_node(pos, number)
|
||||
local key = minetest.hash_node_position(pos)
|
||||
NumbersToBeRecycled[key] = number
|
||||
end
|
||||
|
||||
function techage.post_remove_node(pos)
|
||||
local key = minetest.hash_node_position(pos)
|
||||
NumbersToBeRecycled[key] = nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Node register function
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- Register node for techage communication
|
||||
-- Call this function only at load time!
|
||||
-- Param names: List of node names like {"techage:pusher_off", "techage:pusher_on"}
|
||||
-- Param node_definition: A table according to:
|
||||
-- {
|
||||
-- on_inv_request = func(pos, in_dir, access_type)
|
||||
-- on_pull_item = func(pos, in_dir, num, (opt.) item_name),
|
||||
-- on_push_item = func(pos, in_dir, item),
|
||||
-- on_unpull_item = func(pos, in_dir, item),
|
||||
-- on_recv_message = func(pos, src, topic, payload),
|
||||
-- on_node_load = func(pos), -- LBM function
|
||||
-- on_transfer = func(pos, in_dir, topic, payload),
|
||||
-- }
|
||||
function techage.register_node(names, node_definition)
|
||||
-- store facedir table for all known node names
|
||||
for _,n in ipairs(names) do
|
||||
NodeDef[n] = node_definition
|
||||
end
|
||||
if node_definition.on_pull_item or node_definition.on_push_item or
|
||||
node_definition.is_pusher then
|
||||
Tube:add_secondary_node_names(names)
|
||||
|
||||
for _,n in ipairs(names) do
|
||||
techage.KnownNodes[n] = true
|
||||
end
|
||||
end
|
||||
-- register LBM
|
||||
if node_definition.on_node_load then
|
||||
register_lbm(names[1], names)
|
||||
end
|
||||
|
||||
-- register mvps stopper
|
||||
if has_mesecons then
|
||||
for _, name in ipairs(names) do
|
||||
mesecon.register_mvps_stopper(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Send message functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function techage.not_protected(number, placer_name, clicker_name)
|
||||
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
|
||||
if ninfo and ninfo.pos then
|
||||
return not_protected(ninfo.pos, placer_name, clicker_name)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check the given number value.
|
||||
-- Returns true if the number is valid, point to real node and
|
||||
-- and the node is not protected for the given player_name.
|
||||
function techage.check_number(number, placer_name)
|
||||
if number then
|
||||
if not techage.not_protected(number, placer_name, nil) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check the given list of numbers.
|
||||
-- Returns true if number(s) is/are valid, point to real nodes and
|
||||
-- and the nodes are not protected for the given player_name.
|
||||
function techage.check_numbers(numbers, placer_name)
|
||||
if numbers then
|
||||
for _,num in ipairs(string_split(numbers, " ")) do
|
||||
if not techage.not_protected(num, placer_name, nil) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function techage.send_multi(src, numbers, topic, payload)
|
||||
--print("send_multi", src, numbers, topic)
|
||||
for _,num in ipairs(string_split(numbers, " ")) do
|
||||
local ninfo = NodeInfoCache[num] or update_nodeinfo(num)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_recv_message then
|
||||
techage_counting_hit()
|
||||
ndef.on_recv_message(ninfo.pos, src, topic, payload)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function techage.send_single(src, number, topic, payload)
|
||||
--print("send_single", src, number, topic)
|
||||
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_recv_message then
|
||||
techage_counting_hit()
|
||||
return ndef.on_recv_message(ninfo.pos, src, topic, payload)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- The destination node location is either:
|
||||
-- A) a destination position, specified by pos
|
||||
-- B) a neighbor position, specified by caller pos/outdir, or pos/side
|
||||
-- C) a tubelib2 network connection, specified by caller pos/outdir, or pos/side
|
||||
-- outdir is one of: 1..6
|
||||
-- side is one of: "B", "R", "F", "L", "D", "U"
|
||||
-- network is a tuebelib2 network instance
|
||||
-- opt: nodenames is a table of valid the callee node names
|
||||
function techage.transfer(pos, outdir, topic, payload, network, nodenames)
|
||||
-- determine out-dir
|
||||
if outdir and type(outdir) == "string" then
|
||||
local param2 = techage.get_node_lvm(pos).param2
|
||||
outdir = side_to_dir(outdir, param2)
|
||||
end
|
||||
-- determine destination pos
|
||||
local dpos, indir
|
||||
if network then
|
||||
dpos, indir = network:get_connected_node_pos(pos, outdir)
|
||||
else
|
||||
dpos, indir = tubelib2.get_pos(pos, outdir), outdir
|
||||
end
|
||||
-- check node name
|
||||
local name = techage.get_node_lvm(dpos).name
|
||||
if nodenames and not in_list(nodenames, name) then
|
||||
return false
|
||||
end
|
||||
-- call "on_transfer"
|
||||
local ndef = NodeDef[name]
|
||||
if ndef and ndef.on_transfer then
|
||||
return ndef.on_transfer(dpos, indir, topic, payload)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Beduino functions (see "bep-005_ta_cmnd.md")
|
||||
-------------------------------------------------------------------
|
||||
function techage.beduino_send_cmnd(src, number, topic, payload)
|
||||
--print("beduino_send_cmnd", src, number, topic)
|
||||
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_beduino_receive_cmnd then
|
||||
techage_counting_hit()
|
||||
return ndef.on_beduino_receive_cmnd(ninfo.pos, src, topic, payload or {})
|
||||
end
|
||||
end
|
||||
return 1, ""
|
||||
end
|
||||
|
||||
function techage.beduino_request_data(src, number, topic, payload)
|
||||
--print("beduino_request_data", src, number, topic)
|
||||
local ninfo = NodeInfoCache[number] or update_nodeinfo(number)
|
||||
if ninfo and ninfo.name and ninfo.pos then
|
||||
local ndef = NodeDef[ninfo.name]
|
||||
if ndef and ndef.on_beduino_request_data then
|
||||
techage_counting_hit()
|
||||
return ndef.on_beduino_request_data(ninfo.pos, src, topic, payload or {})
|
||||
end
|
||||
end
|
||||
return 1, ""
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Client side Push/Pull item functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function techage.get_inv_access(pos, out_dir, access_type)
|
||||
local npos, in_dir, name = get_dest_node(pos, out_dir)
|
||||
if npos and NodeDef[name] and NodeDef[name].on_inv_request then
|
||||
return NodeDef[name].on_inv_request(npos, in_dir, access_type)
|
||||
end
|
||||
end
|
||||
|
||||
function techage.pull_items(pos, out_dir, num, item_name)
|
||||
local npos, in_dir, name = get_dest_node(pos, out_dir)
|
||||
if npos and NodeDef[name] and NodeDef[name].on_pull_item then
|
||||
return NodeDef[name].on_pull_item(npos, in_dir, num, item_name)
|
||||
end
|
||||
end
|
||||
|
||||
function techage.push_items(pos, out_dir, stack, idx)
|
||||
local npos, in_dir, name = get_dest_node(pos, out_dir)
|
||||
if npos and NodeDef[name] and NodeDef[name].on_push_item then
|
||||
return NodeDef[name].on_push_item(npos, in_dir, stack, idx)
|
||||
elseif is_air_like(name) or is_cart_available(npos) then
|
||||
minetest.add_item(npos, stack)
|
||||
return true
|
||||
end
|
||||
return stack
|
||||
end
|
||||
|
||||
-- Check for recursion and too long distances
|
||||
local start_pos
|
||||
function techage.safe_push_items(pos, out_dir, stack, idx)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.pushing then
|
||||
if not start_pos then
|
||||
start_pos = pos
|
||||
mem.pushing = true
|
||||
local res = techage.push_items(pos, out_dir, stack, idx)
|
||||
mem.pushing = nil
|
||||
start_pos = nil
|
||||
return res
|
||||
else
|
||||
local npos, in_dir, name = get_dest_node(pos, out_dir)
|
||||
if vector.distance(start_pos, npos) < (Tube.max_tube_length or 100) then
|
||||
mem.pushing = true
|
||||
local res = techage.push_items(pos, out_dir, stack, idx)
|
||||
mem.pushing = nil
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
return stack
|
||||
end
|
||||
|
||||
function techage.unpull_items(pos, out_dir, stack)
|
||||
local npos, in_dir, name = get_dest_node(pos, out_dir)
|
||||
if npos and NodeDef[name] and NodeDef[name].on_unpull_item then
|
||||
return NodeDef[name].on_unpull_item(npos, in_dir, stack)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Server side helper functions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-- Get the given number of items from the inv. The position within the list
|
||||
-- is incremented each time so that different item stacks will be considered.
|
||||
-- Returns nil if ItemList is empty.
|
||||
function techage.get_items(pos, inv, listname, num)
|
||||
if inv:is_empty(listname) then
|
||||
return nil
|
||||
end
|
||||
local size = inv:get_size(listname)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.ta_startpos = mem.ta_startpos or 0
|
||||
for idx = mem.ta_startpos, mem.ta_startpos+size do
|
||||
idx = (idx % size) + 1
|
||||
local items = inv:get_stack(listname, idx)
|
||||
if items:get_count() > 0 then
|
||||
local taken = items:take_item(num)
|
||||
inv:set_stack(listname, idx, items)
|
||||
mem.ta_startpos = idx
|
||||
return taken
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Put the given stack into the given ItemList/inventory.
|
||||
-- Function returns:
|
||||
-- - true, if all items are moved
|
||||
-- - false, if no item is moved
|
||||
-- - leftover, if less than all items are moved
|
||||
-- (true/false is the legacy mode and can't be removed)
|
||||
function techage.put_items(inv, listname, item, idx)
|
||||
local leftover
|
||||
if idx and inv and idx <= inv:get_size(listname) then
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
leftover = stack:add_item(item)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
elseif inv then
|
||||
leftover = inv:add_item(listname, item)
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
local cnt = leftover:get_count()
|
||||
if cnt == item:get_count() then
|
||||
return false
|
||||
elseif cnt == 0 then
|
||||
return true
|
||||
else
|
||||
return leftover
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Return "full", "loaded", or "empty" depending
|
||||
-- on the inventory load.
|
||||
-- Full is returned, when no empty stack is available.
|
||||
function techage.get_inv_state(inv, listname)
|
||||
local state
|
||||
if inv:is_empty(listname) then
|
||||
state = "empty"
|
||||
else
|
||||
local list = inv:get_list(listname)
|
||||
state = "full"
|
||||
for _, item in ipairs(list) do
|
||||
if item:is_empty() then
|
||||
return "loaded"
|
||||
end
|
||||
end
|
||||
end
|
||||
return state
|
||||
end
|
||||
|
||||
-- Beduino variant
|
||||
function techage.get_inv_state_num(inv, listname)
|
||||
local state
|
||||
if inv:is_empty(listname) then
|
||||
state = 0
|
||||
else
|
||||
local list = inv:get_list(listname)
|
||||
state = 2
|
||||
for _, item in ipairs(list) do
|
||||
if item:is_empty() then
|
||||
return 1
|
||||
end
|
||||
end
|
||||
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
|
||||
})
|
@ -1,118 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Configured inventory lib
|
||||
Assuming the inventory has the name "conf"
|
||||
Otherwise the name has to be provided as argument
|
||||
|
||||
]]--
|
||||
|
||||
local StackName = ... or "conf"
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
|
||||
local inv_lib = {}
|
||||
|
||||
function inv_lib.preassigned_stacks(pos, xsize, ysize)
|
||||
local inv = M(pos):get_inventory()
|
||||
local tbl = {}
|
||||
for idx = 1, xsize * ysize do
|
||||
local item_name = inv:get_stack(StackName, idx):get_name()
|
||||
if item_name ~= "" then
|
||||
local x = (idx - 1) % xsize
|
||||
local y = math.floor((idx - 1) / xsize)
|
||||
tbl[#tbl+1] = "item_image["..x..","..y..";1,1;"..item_name.."]"
|
||||
end
|
||||
end
|
||||
return table.concat(tbl, "")
|
||||
end
|
||||
|
||||
function inv_lib.item_filter(pos, size)
|
||||
local inv = M(pos):get_inventory()
|
||||
local filter = {}
|
||||
for idx = 1, size do
|
||||
local item_name = inv:get_stack(StackName, idx):get_name()
|
||||
if item_name == "" then item_name = "unconfigured" end
|
||||
if not filter[item_name] then
|
||||
filter[item_name] = {}
|
||||
end
|
||||
table.insert(filter[item_name], idx)
|
||||
end
|
||||
return filter
|
||||
end
|
||||
|
||||
function inv_lib.allow_conf_inv_put(pos, listname, index, stack, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
local list = inv:get_list(listname)
|
||||
|
||||
if list[index]:get_count() == 0 then
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function inv_lib.allow_conf_inv_take(pos, listname, index, stack, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_stack(listname, index, nil)
|
||||
return 0
|
||||
end
|
||||
|
||||
function inv_lib.allow_conf_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
local stack = inv:get_stack(to_list, to_index)
|
||||
|
||||
if stack:get_count() == 0 then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function inv_lib.put_items(pos, inv, listname, item, stacks, idx)
|
||||
local name = item:get_name()
|
||||
local count = item:get_count()
|
||||
for _, i in ipairs(stacks or {}) do
|
||||
if not idx or idx == i then
|
||||
local stack = inv:get_stack(listname, i)
|
||||
local leftover = stack:add_item({name = name, count = count})
|
||||
count = leftover:get_count()
|
||||
inv:set_stack(listname, i, stack)
|
||||
if count == 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
if count > 0 then
|
||||
return ItemStack({name = name, count = count})
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function inv_lib.take_item(pos, inv, listname, num, stacks)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.ta_startpos = mem.ta_startpos or 1
|
||||
local size = #(stacks or {})
|
||||
for i = 1, size do
|
||||
local idx = stacks[((i + mem.ta_startpos) % size) + 1]
|
||||
local stack = inv:get_stack(listname, idx)
|
||||
local taken = stack:take_item(num)
|
||||
if taken:get_count() > 0 then
|
||||
inv:set_stack(listname, idx, stack)
|
||||
mem.ta_startpos = mem.ta_startpos + i
|
||||
return taken
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return inv_lib
|
@ -1,71 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Count techage commands player related
|
||||
|
||||
]]--
|
||||
|
||||
local PlayerName
|
||||
local PlayerPoints = {}
|
||||
local LastPlayerPoints = {}
|
||||
local S = techage.S
|
||||
|
||||
local MAX_POINTS = tonumber(minetest.settings:get("techage_command_limit")) or 1200
|
||||
|
||||
function techage.counting_start(player_name)
|
||||
PlayerName = player_name
|
||||
PlayerPoints[PlayerName] = PlayerPoints[PlayerName] or 0
|
||||
end
|
||||
|
||||
function techage.counting_stop()
|
||||
PlayerName = nil
|
||||
end
|
||||
|
||||
function techage.counting_hit()
|
||||
if PlayerName then
|
||||
PlayerPoints[PlayerName] = PlayerPoints[PlayerName] + 1
|
||||
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
|
||||
local obj = minetest.get_player_by_name(name)
|
||||
if obj then
|
||||
minetest.chat_send_player(name,
|
||||
S("[techage] The limit for 'number of commands per minute' has been exceeded.") ..
|
||||
" " .. string.format(MAX_POINTS .. " " .. S("is allowed. Current value is") .. " " .. val));
|
||||
minetest.log("action", "[techage] " .. name ..
|
||||
" exceeds the limit for commands per minute. value = " .. val)
|
||||
local factor = 100 / (obj:get_armor_groups().fleshy or 100)
|
||||
obj:punch(obj, 1.0, {full_punch_interval=1.0, damage_groups = {fleshy=factor * 5}})
|
||||
end
|
||||
end
|
||||
end
|
||||
LastPlayerPoints = table.copy(PlayerPoints)
|
||||
PlayerPoints = {}
|
||||
minetest.after(60, output)
|
||||
end
|
||||
|
||||
minetest.after(60, output)
|
||||
|
||||
|
||||
minetest.register_chatcommand("ta_limit", {
|
||||
description = "Get your current techage command limit value",
|
||||
func = function(name)
|
||||
local num = LastPlayerPoints[name] or 0
|
||||
return true, S("Your current value is") .. " " .. num .. " " .. S("per minute") .. ". " ..
|
||||
MAX_POINTS .. " " .. S("is allowed")
|
||||
end
|
||||
})
|
@ -1,117 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
Copyright (C) 2020 Thomas S.
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Fake Player
|
||||
|
||||
]]--
|
||||
|
||||
-- Map method names to their return values
|
||||
local methods = {
|
||||
get_pos = { x = 0, y = 0, z = 0 },
|
||||
set_pos = nil,
|
||||
moveto = nil,
|
||||
punch = nil,
|
||||
right_click = nil,
|
||||
get_hp = 20,
|
||||
set_hp = nil,
|
||||
get_inventory = nil,
|
||||
get_wield_list = "",
|
||||
get_wield_index = 0,
|
||||
get_wielded_item = ItemStack(),
|
||||
set_wielded_item = true,
|
||||
set_armor_groups = nil,
|
||||
get_armor_groups = {},
|
||||
set_animation = nil,
|
||||
get_animation = {},
|
||||
set_animation_frame_speed = nil,
|
||||
set_attach = nil,
|
||||
get_attach = nil,
|
||||
set_detach = nil,
|
||||
get_bone_position = {},
|
||||
set_properties = nil,
|
||||
get_properties = {},
|
||||
is_player = false,
|
||||
get_nametag_attributes = {},
|
||||
set_nametag_attributes = nil,
|
||||
get_player_name = "",
|
||||
get_player_velocity = nil,
|
||||
add_player_velocity = nil,
|
||||
get_look_dir = vector.new(0, 0, 1),
|
||||
get_look_vertical = 0,
|
||||
get_look_horizontal = 0,
|
||||
set_look_vertical = nil,
|
||||
set_look_horizontal = nil,
|
||||
get_look_pitch = 0,
|
||||
get_look_yaw = 0,
|
||||
set_look_pitch = nil,
|
||||
set_look_yaw = nil,
|
||||
get_breath = 10,
|
||||
set_breath = nil,
|
||||
set_fov = nil,
|
||||
get_fov = 0,
|
||||
set_attribute = nil,
|
||||
get_attribute = nil,
|
||||
get_meta = nil,
|
||||
set_inventory_formspec = nil,
|
||||
get_inventory_formspec = "",
|
||||
set_formspec_prepend = nil,
|
||||
get_formspec_prepend = "",
|
||||
get_player_control = {},
|
||||
get_player_control_bits = 0,
|
||||
set_physics_override = nil,
|
||||
get_physics_override = {},
|
||||
hud_add = 0,
|
||||
hud_remove = nil,
|
||||
hud_change = nil,
|
||||
hud_get = {},
|
||||
hud_set_flags = nil,
|
||||
hud_get_flags = {},
|
||||
hud_set_hotbar_itemcount = nil,
|
||||
hud_get_hotbar_itemcount = 8,
|
||||
hud_set_hotbar_image = nil,
|
||||
hud_get_hotbar_image = "",
|
||||
hud_set_hotbar_selected_image = nil,
|
||||
hud_get_hotbar_selected_image = "",
|
||||
set_sky = nil,
|
||||
get_sky = {},
|
||||
get_sky_color = {},
|
||||
set_sun = nil,
|
||||
get_sun = {},
|
||||
set_moon = nil,
|
||||
get_moon = {},
|
||||
set_stars = nil,
|
||||
get_stars = {},
|
||||
set_clouds = nil,
|
||||
get_clouds = {},
|
||||
override_day_night_ratio = nil,
|
||||
get_day_night_ratio = nil,
|
||||
set_local_animation = nil,
|
||||
get_local_animation = {},
|
||||
set_eye_offset = nil,
|
||||
get_eye_offset = {},
|
||||
send_mapblock = nil,
|
||||
}
|
||||
|
||||
techage.Fake_player = {}
|
||||
techage.Fake_player.__index = techage.Fake_player
|
||||
|
||||
function techage.Fake_player:new()
|
||||
local fake_player = {}
|
||||
setmetatable(fake_player, techage.Fake_player)
|
||||
return fake_player
|
||||
end
|
||||
|
||||
|
||||
for method_name, return_value in pairs(methods) do
|
||||
techage.Fake_player[method_name] = function(self, ...)
|
||||
return return_value
|
||||
end
|
||||
end
|
@ -1,150 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Firebox basic functions
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
techage.firebox = {}
|
||||
|
||||
techage.firebox.Burntime = {
|
||||
["techage:charcoal"] = 1, -- will be replaced by burntime
|
||||
["default:coal_lump"] = 1,
|
||||
["default:coalblock"] = 1,
|
||||
["techage:oil_source"] = 1,
|
||||
["techage:gas"] = 1,
|
||||
["techage:gasoline"] = 1,
|
||||
["techage:naphtha"] = 1,
|
||||
["techage:fueloil"] = 1,
|
||||
}
|
||||
|
||||
techage.firebox.ValidOilFuels = {
|
||||
["techage:gasoline"] = 1, -- category
|
||||
["techage:naphtha"] = 2,
|
||||
["techage:fueloil"] = 3,
|
||||
["techage:oil_source"] = 4,
|
||||
}
|
||||
|
||||
|
||||
local function determine_burntimes()
|
||||
for k,_ in pairs(techage.firebox.Burntime)do
|
||||
local fuel,_ = minetest.get_craft_result({method = "fuel", width = 1, items = {k}})
|
||||
techage.firebox.Burntime[k] = fuel.time
|
||||
end
|
||||
end
|
||||
minetest.register_on_mods_loaded(determine_burntimes)
|
||||
|
||||
function techage.firebox.formspec(nvm)
|
||||
local fuel_percent = 0
|
||||
if nvm.running then
|
||||
fuel_percent = ((nvm.burn_cycles or 1) * 100) / (nvm.burn_cycles_total or 1)
|
||||
end
|
||||
return "size[8,6]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize( "#000000", S("Firebox")).."]"..
|
||||
"list[current_name;fuel;3,1;1,1;]"..
|
||||
"image[4,1;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
fuel_percent..":default_furnace_fire_fg.png]"..
|
||||
"list[current_player;main;0,2.3;8,4;]"..
|
||||
"listring[current_name;fuel]"..
|
||||
"listring[current_player;main]"..
|
||||
default.get_hotbar_bg(0, 2.3)
|
||||
end
|
||||
|
||||
function techage.firebox.can_dig(pos, player)
|
||||
local inv = M(pos):get_inventory()
|
||||
return inv:is_empty("fuel")
|
||||
end
|
||||
|
||||
function techage.firebox.allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
if techage.firebox.Burntime[stack:get_name()] then
|
||||
return stack:get_count()
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function techage.firebox.allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
function techage.firebox.on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", techage.firebox.formspec(nvm))
|
||||
end
|
||||
|
||||
function techage.firebox.swap_node(pos, name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == name then
|
||||
return
|
||||
end
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
function techage.firebox.get_fuel(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local items = inv:get_stack("fuel", 1)
|
||||
if items:get_count() > 0 then
|
||||
local taken = items:take_item(1)
|
||||
inv:set_stack("fuel", 1, items)
|
||||
return taken
|
||||
end
|
||||
end
|
||||
|
||||
function techage.firebox.has_fuel(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local items = inv:get_stack("fuel", 1)
|
||||
return items:get_count() > 0
|
||||
end
|
||||
|
||||
function techage.firebox.is_free_position(pos, player_name)
|
||||
local pos2 = techage.get_pos(pos, 'F')
|
||||
if minetest.is_protected(pos2, player_name) then
|
||||
minetest.chat_send_player(player_name, S("[TA] Area is protected!"))
|
||||
return false
|
||||
end
|
||||
local node = techage.get_node_lvm(pos2)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if not ndef or not ndef.buildable_to then
|
||||
minetest.chat_send_player(player_name, S("[TA] Not enough space!"))
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function techage.firebox.set_firehole(pos, on)
|
||||
local param2 = techage.get_node_lvm(pos).param2
|
||||
local pos2 = techage.get_pos(pos, 'F')
|
||||
if on == true then
|
||||
minetest.swap_node(pos2, {name="techage:coalfirehole_on", param2 = param2})
|
||||
elseif on == false then
|
||||
minetest.swap_node(pos2, {name="techage:coalfirehole", param2 = param2})
|
||||
else
|
||||
local node = techage.get_node_lvm(pos2)
|
||||
if node.name == "techage:coalfirehole" or node.name == "techage:coalfirehole_on" then
|
||||
minetest.swap_node(pos2, {name="air"})
|
||||
end
|
||||
end
|
||||
end
|
@ -1,955 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020-2023 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
|
||||
|
||||
-- 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
|
||||
|
||||
-- playername is needed for carts, to attach the player to the cart entity
|
||||
local function set_node(item, playername)
|
||||
local dest_pos = item.dest_pos
|
||||
local name = item.name or "air"
|
||||
local param2 = item.param2 or 0
|
||||
local nvm = techage.get_nvm(item.base_pos)
|
||||
local node = techage.get_node_lvm(dest_pos)
|
||||
local ndef1 = minetest.registered_nodes[name]
|
||||
local ndef2 = minetest.registered_nodes[node.name]
|
||||
|
||||
nvm.running = false
|
||||
M(item.base_pos):set_string("status", S("Stopped"))
|
||||
if ndef1 and ndef2 then
|
||||
if minecart.is_cart(name) and (minecart.is_rail(dest_pos, node.name) or minecart.is_cart(name)) then
|
||||
local player = playername and minetest.get_player_by_name(playername)
|
||||
minecart.place_and_start_cart(dest_pos, {name = name, param2 = param2}, item.cartdef, player)
|
||||
return
|
||||
elseif ndef2.buildable_to then
|
||||
local meta = M(dest_pos)
|
||||
if name ~= "techage:moveblock" then
|
||||
minetest.set_node(dest_pos, {name=name, param2=param2})
|
||||
meta:from_table(item.metadata or {})
|
||||
meta:set_string("ta_move_block", "")
|
||||
meta:set_int("ta_door_locked", 1)
|
||||
end
|
||||
return
|
||||
end
|
||||
local meta = M(dest_pos)
|
||||
if not meta:contains("ta_move_block") then
|
||||
meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
|
||||
return
|
||||
end
|
||||
elseif ndef1 then
|
||||
if name ~= "techage:moveblock" then
|
||||
minetest.add_item(dest_pos, ItemStack(name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Entity monitoring
|
||||
-------------------------------------------------------------------------------
|
||||
local queue = {}
|
||||
local first = 0
|
||||
local last = -1
|
||||
|
||||
local function push(item)
|
||||
last = last + 1
|
||||
queue[last] = item
|
||||
end
|
||||
|
||||
local function pop()
|
||||
if first > last then return end
|
||||
local item = queue[first]
|
||||
queue[first] = nil -- to allow garbage collection
|
||||
first = first + 1
|
||||
return item
|
||||
end
|
||||
|
||||
local function monitoring()
|
||||
local num = last - first + 1
|
||||
for _ = 1, num do
|
||||
local item = pop()
|
||||
if item.ttl >= techage.SystemTime then
|
||||
-- still valud
|
||||
push(item)
|
||||
elseif item.ttl ~= 0 then
|
||||
set_node(item)
|
||||
end
|
||||
end
|
||||
minetest.after(1, monitoring)
|
||||
end
|
||||
minetest.after(1, monitoring)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
local num = last - first + 1
|
||||
for _ = 1, num do
|
||||
local item = pop()
|
||||
if item.ttl ~= 0 then
|
||||
set_node(item)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function monitoring_add_entity(item)
|
||||
item.ttl = techage.SystemTime + 1
|
||||
push(item)
|
||||
end
|
||||
|
||||
local function monitoring_del_entity(item)
|
||||
-- Mark as timed out
|
||||
item.ttl = 0
|
||||
end
|
||||
|
||||
local function monitoring_trigger_entity(item)
|
||||
item.ttl = techage.SystemTime + 1
|
||||
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, max_dist)
|
||||
local x,y,z = unpack(string.split(s, ","))
|
||||
x = tonumber(x) or 0
|
||||
y = tonumber(y) or 0
|
||||
z = tonumber(z) or 0
|
||||
if x and y and z then
|
||||
if not max_dist or (math.abs(x) + math.abs(y) + math.abs(z)) <= max_dist then
|
||||
return {x = x, y = y, z = z}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function flylib.to_path(s, max_dist)
|
||||
local tPath
|
||||
local dist = 0
|
||||
|
||||
for _, line in ipairs(strsplit(s or "")) 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 by @1 blocks !!", dist - max_dist)
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Protect the doors from being opened by hand
|
||||
-------------------------------------------------------------------------------
|
||||
local function new_on_rightclick(old_on_rightclick)
|
||||
return function(pos, node, clicker, itemstack, pointed_thing)
|
||||
if M(pos):contains("ta_door_locked") then
|
||||
return itemstack
|
||||
end
|
||||
if old_on_rightclick then
|
||||
return old_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function flylib.protect_door_from_being_opened(name)
|
||||
-- Change on_rightclick function.
|
||||
local ndef = minetest.registered_nodes[name]
|
||||
if ndef then
|
||||
local old_on_rightclick = ndef.on_rightclick
|
||||
minetest.override_item(ndef.name, {
|
||||
on_rightclick = new_on_rightclick(old_on_rightclick)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Entity / Move / Attach / Detach
|
||||
-------------------------------------------------------------------------------
|
||||
local MIN_SPEED = 0.4
|
||||
local MAX_SPEED = 8
|
||||
local CORNER_SPEED = 4
|
||||
|
||||
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, distance)
|
||||
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(distance)
|
||||
-- Calc entity rotation, which is relative to the parent's rotation
|
||||
local rot = parent:get_rotation()
|
||||
if self.param2 >= 20 then
|
||||
distance = rotate(distance, 2 * math.pi - rot.y)
|
||||
distance.y = -distance.y
|
||||
distance.x = -distance.x
|
||||
rot.y = rot.y - yaw
|
||||
elseif self.param2 < 4 then
|
||||
distance = rotate(distance, 2 * math.pi - rot.y)
|
||||
rot.y = rot.y - yaw
|
||||
end
|
||||
distance = vector.multiply(distance, 29)
|
||||
obj:set_attach(parent, "", distance, 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
|
||||
-- distance (optional) is the attach distance to the center of the entity
|
||||
local function attach_objects(pos, offs, parent, yoffs, distance)
|
||||
local pos1 = vector.add(pos, offs)
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos1, 0.9)) do
|
||||
-- keep relative object position
|
||||
distance = distance or vector.subtract(obj:get_pos(), pos)
|
||||
local entity = obj:get_luaentity()
|
||||
if entity then
|
||||
local mod = entity.name:gmatch("(.-):")()
|
||||
if techage.RegisteredMobsMods[mod] then
|
||||
distance.y = distance.y + yoffs
|
||||
attach_single_object(parent, obj, distance)
|
||||
end
|
||||
elseif obj:is_player() then
|
||||
attach_single_object(parent, obj, distance)
|
||||
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 and self.item then
|
||||
local playername = self.players and self.players[1] and self.players[1].name
|
||||
detach_objects(pos, self)
|
||||
monitoring_del_entity(self.item)
|
||||
minetest.after(0.1, obj.remove, obj)
|
||||
set_node(self.item, playername)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create a node entitiy.
|
||||
-- * base_pos is controller block related
|
||||
-- * start_pos and dest_pos are entity positions
|
||||
local function node_to_entity(base_pos, start_pos, dest_pos)
|
||||
local meta = M(start_pos)
|
||||
local node, metadata, cartdef
|
||||
|
||||
node = techage.get_node_lvm(start_pos)
|
||||
if minecart.is_cart(node.name) then
|
||||
cartdef = minecart.remove_cart(start_pos)
|
||||
elseif 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", "")
|
||||
meta:set_string("ta_block_locked", "true")
|
||||
elseif not meta:contains("ta_block_locked") then
|
||||
-- Block with other metadata
|
||||
node = techage.get_node_lvm(start_pos)
|
||||
metadata = meta:to_table()
|
||||
minetest.after(0.1, minetest.remove_node, start_pos)
|
||||
else
|
||||
return
|
||||
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.param2 = node.param2
|
||||
self.item = {
|
||||
name = node.name,
|
||||
param2 = node.param2,
|
||||
metadata = metadata or {},
|
||||
dest_pos = dest_pos,
|
||||
base_pos = base_pos,
|
||||
cartdef = cartdef,
|
||||
}
|
||||
monitoring_add_entity(self.item)
|
||||
|
||||
-- Prepare for attachments
|
||||
self.players = {}
|
||||
self.entities = {}
|
||||
-- Prepare for path walk
|
||||
self.path_idx = 1
|
||||
return obj, self.item.cartdef ~= nil
|
||||
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, next_pos, dir, is_corner)
|
||||
local self = obj:get_luaentity()
|
||||
self.next_pos = next_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.lmove, 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
|
||||
|
||||
minetest.register_entity("techage:move_item", {
|
||||
initial_properties = {
|
||||
pointable = true,
|
||||
makes_footstep_sound = true,
|
||||
static_save = false,
|
||||
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},
|
||||
},
|
||||
|
||||
on_step = function(self, dtime, moveresult)
|
||||
local stop_obj = function(obj, self)
|
||||
local next_pos = self.next_pos
|
||||
obj:move_to(self.next_pos, true)
|
||||
obj:set_acceleration({x=0, y=0, z=0})
|
||||
obj:set_velocity({x=0, y=0, z=0})
|
||||
self.next_pos = nil
|
||||
self.old_dist = nil
|
||||
return next_pos
|
||||
end
|
||||
|
||||
if self.next_pos then
|
||||
local obj = self.object
|
||||
local pos = obj:get_pos()
|
||||
local dist = vector.distance(pos, self.next_pos)
|
||||
local speed = calc_speed(obj:get_velocity())
|
||||
self.old_dist = self.old_dist or dist
|
||||
|
||||
if self.lmove and self.lmove[self.path_idx] then
|
||||
local min_dist = math.min(1, self.max_speed / 8)
|
||||
if dist < min_dist or dist > self.old_dist then
|
||||
-- change of direction
|
||||
local next_pos = stop_obj(obj, self)
|
||||
if not moveon_entity(obj, self, next_pos) then
|
||||
minetest.after(0.5, entity_to_node, next_pos, obj)
|
||||
end
|
||||
return
|
||||
end
|
||||
elseif dist < 0.05 or dist > self.old_dist then
|
||||
-- Landing
|
||||
local next_pos = stop_obj(obj, self)
|
||||
local dest_pos = self.item.dest_pos or next_pos
|
||||
minetest.after(0.5, entity_to_node, dest_pos, obj)
|
||||
return
|
||||
end
|
||||
|
||||
self.old_dist = dist
|
||||
|
||||
-- Braking or limit max speed
|
||||
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
|
||||
|
||||
monitoring_trigger_entity(self.item)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local function is_valid_dest(pos)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if techage.is_air_like(node.name) then
|
||||
return true
|
||||
end
|
||||
if minecart.is_rail(pos, node.name) or minecart.is_cart(node.name) 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)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if not minecart.is_rail(pos, node.name) then
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
return node.name ~= "air" and techage.can_dig_node(node.name, ndef) or minecart.is_cart(node.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Move node from 'pos1' to the destination, calculated by means of 'lmove'
|
||||
-- * pos and meta are controller block related
|
||||
-- * lmove is the movement as a list of `moves`
|
||||
-- * height is move block height as value between 0 and 1 and used to calculate the offset
|
||||
-- for the attached object (player).
|
||||
local function move_node(pos, meta, pos1, lmove, max_speed, height)
|
||||
local pos2 = next_path_pos(pos1, lmove, 1)
|
||||
local offs = dest_offset(lmove)
|
||||
local dest_pos = vector.add(pos1, offs)
|
||||
-- optional for non-player objects
|
||||
local yoffs = meta:get_float("offset")
|
||||
|
||||
if pos2 then
|
||||
local dir = determine_dir(pos1, pos2)
|
||||
local obj, is_cart = node_to_entity(pos, pos1, dest_pos)
|
||||
|
||||
if obj then
|
||||
if is_cart then
|
||||
attach_objects(pos1, 0, obj, yoffs, {x = 0, y = -0.4, z = 0})
|
||||
else
|
||||
local offs = {x=0, y=height or 1, z=0}
|
||||
attach_objects(pos1, 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(pos1, dir, obj, yoffs)
|
||||
end
|
||||
end
|
||||
end
|
||||
local self = obj:get_luaentity()
|
||||
self.path_idx = 2
|
||||
self.lmove = lmove
|
||||
self.max_speed = max_speed
|
||||
self.yoffs = yoffs
|
||||
move_entity(obj, pos2, dir)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Default Move Mode
|
||||
--
|
||||
|
||||
-- Move the nodes from nvm.lpos1 to nvm.lpos2
|
||||
-- * nvm.lpos1 is a list of nodes
|
||||
-- * lmove is the movement as a list of `moves`
|
||||
-- * pos, meta, and nvm are controller block related
|
||||
--- height is move block height as value between 0 and 1 and used to calculate the offset
|
||||
-- for the attached object (player).
|
||||
local function multi_move_nodes(pos, meta, nvm, lmove, max_speed, height, move2to1)
|
||||
local owner = meta:get_string("owner")
|
||||
techage.counting_add(owner, #lmove, #nvm.lpos1 * #lmove)
|
||||
|
||||
for idx = 1, #nvm.lpos1 do
|
||||
local pos1 = nvm.lpos1[idx]
|
||||
local pos2 = nvm.lpos2[idx]
|
||||
--print("multi_move_nodes", idx, P2S(pos1), P2S(pos2))
|
||||
|
||||
if move2to1 then
|
||||
pos1, pos2 = pos2, pos1
|
||||
end
|
||||
|
||||
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
|
||||
if move_node(pos, meta, pos1, lmove, max_speed, height) == false then
|
||||
meta:set_string("status", S("No valid node at the start position"))
|
||||
return false
|
||||
end
|
||||
else
|
||||
if not is_simple_node(pos1) then
|
||||
meta:set_string("status", S("No valid node at the start position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid node at the start position") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("No valid destination position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid destination position") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
meta:set_string("status", S("Start position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Start position is protected") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("Destination position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Destination position is protected") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
meta:set_string("status", S("Running"))
|
||||
return true
|
||||
end
|
||||
|
||||
-- Move the nodes from lpos1 to lpos2.
|
||||
-- * lpos1 is a list of nodes
|
||||
-- * lpos2 = lpos1 + move
|
||||
-- * pos and meta are controller block related
|
||||
-- * height is move block height as value between 0 and 1 and used to calculate the offset
|
||||
-- for the attached object (player).
|
||||
local function move_nodes(pos, meta, lpos1, move, max_speed, height)
|
||||
local owner = meta:get_string("owner")
|
||||
lpos1 = lpos1 or {}
|
||||
techage.counting_add(owner, #lpos1)
|
||||
|
||||
local lpos2 = {}
|
||||
for idx = 1, #lpos1 do
|
||||
|
||||
local pos1 = lpos1[idx]
|
||||
local pos2 = vector.add(lpos1[idx], move)
|
||||
lpos2[idx] = 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, meta, pos1, {move}, max_speed, height)
|
||||
else
|
||||
if not is_simple_node(pos1) then
|
||||
meta:set_string("status", S("No valid node at the start position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid node at the start position") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("No valid destination position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid destination position") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false, lpos1
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
meta:set_string("status", S("Start position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Start position is protected") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("Destination position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Destination position is protected") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false, lpos1
|
||||
end
|
||||
end
|
||||
|
||||
meta:set_string("status", S("Running"))
|
||||
return true, lpos2
|
||||
end
|
||||
|
||||
--
|
||||
-- Teleport Mode
|
||||
--
|
||||
local function is_player_available(lpos1)
|
||||
if #lpos1 == 1 then
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(lpos1[1], 0.9)) do
|
||||
if obj:is_player() then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function teleport(base_pos, pos1, pos2, meta, owner, lmove, max_speed)
|
||||
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
|
||||
local node1 = techage.get_node_lvm(pos1)
|
||||
local node2 = techage.get_node_lvm(pos2)
|
||||
if techage.is_air_like(node1.name) and techage.is_air_like(node2.name) then
|
||||
minetest.swap_node(pos1, {name = "techage:moveblock", param2 = 0})
|
||||
if move_node(base_pos, meta, pos1, lmove, max_speed, 0) == false then
|
||||
meta:set_string("status", S("No valid start position"))
|
||||
return false
|
||||
end
|
||||
else
|
||||
if not techage.is_air_like(node1.name) then
|
||||
meta:set_string("status", S("No valid start position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid start position") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("No valid destination position"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("No valid destination position") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
if minetest.is_protected(pos1, owner) then
|
||||
meta:set_string("status", S("Start position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Start position is protected") .. " at " .. P2S(pos1))
|
||||
else
|
||||
meta:set_string("status", S("Destination position is protected"))
|
||||
minetest.chat_send_player(owner, " [techage] " .. S("Destination position is protected") .. " at " .. P2S(pos2))
|
||||
end
|
||||
return false
|
||||
end
|
||||
meta:set_string("status", S("Running"))
|
||||
return true
|
||||
end
|
||||
|
||||
-- Move the player from nvm.lpos1 to nvm.lpos2
|
||||
-- * nvm.lpos1 is a list of length one(!) with the not to be moved block below the player
|
||||
-- * lmove is the movement as a list of `moves`
|
||||
-- * pos, meta, and nvm are controller block related
|
||||
local function multi_teleport_player(base_pos, meta, nvm, lmove, max_speed, move2to1)
|
||||
local owner = meta:get_string("owner")
|
||||
techage.counting_add(owner, #lmove, #nvm.lpos1 * #lmove)
|
||||
|
||||
local pos1 = vector.add(nvm.lpos1[1], {x=0, y=1, z=0})
|
||||
local pos2 = vector.add(nvm.lpos2[1], {x=0, y=1, z=0})
|
||||
|
||||
if move2to1 then
|
||||
pos1, pos2 = pos2, pos1
|
||||
end
|
||||
|
||||
return teleport(base_pos, pos1, pos2, meta, owner, lmove, max_speed)
|
||||
end
|
||||
|
||||
-- Move the player from lpos1 to lpos2.
|
||||
-- * lpos1 is a list of length one(!) with the not to be moved block below the player
|
||||
-- * lpos2 = lpos1 + move
|
||||
-- * pos and meta are controller block related
|
||||
local function teleport_player(base_pos, meta, lpos1, move, max_speed)
|
||||
local owner = meta:get_string("owner")
|
||||
lpos1 = lpos1 or {}
|
||||
techage.counting_add(owner, #lpos1)
|
||||
|
||||
local pos1 = vector.add(lpos1[1], {x=0, y=1, z=0})
|
||||
local pos2 = vector.add(pos1, move)
|
||||
|
||||
return teleport(base_pos, pos1, pos2, meta, owner, {move}, max_speed), nil
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
-- API
|
||||
--------------------------------------------------------------------------------------
|
||||
|
||||
-- move2to1 is the direction and is true for 'from pos2 to pos1'
|
||||
-- Move path and other data is stored as meta data of pos
|
||||
function flylib.move_to_other_pos(pos, move2to1)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local lmove, 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 teleport_mode = meta:get_string("teleport_mode") == "enable"
|
||||
|
||||
if err or nvm.running 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(lmove)
|
||||
if move2to1 then
|
||||
lmove = reverse_path(lmove)
|
||||
end
|
||||
-- calc destination positions
|
||||
nvm.lpos2 = lvect_add_vec(nvm.lpos1, offs)
|
||||
local lpos = move2to1 and nvm.lpos2 or nvm.lpos1
|
||||
|
||||
if teleport_mode and is_player_available(lpos) then
|
||||
nvm.running = multi_teleport_player(pos, meta, nvm, lmove, max_speed, move2to1)
|
||||
elseif not teleport_mode then
|
||||
nvm.running = multi_move_nodes(pos, meta, nvm, lmove, max_speed, height, move2to1)
|
||||
end
|
||||
nvm.moveBA = nvm.running and not move2to1
|
||||
return nvm.running
|
||||
end
|
||||
|
||||
-- `move` the movement as a vector
|
||||
function flylib.move_to(pos, move)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local height = techage.in_range(meta:contains("height") and meta:get_float("height") or 1, 0, 1)
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
local teleport_mode = meta:get_string("teleport_mode") == "enable"
|
||||
|
||||
if nvm.running then return false end
|
||||
|
||||
-- TODO: Not working so far. There is no known 'nvm.lastpos' as start pos.
|
||||
--if teleport_mode and is_player_available(nvm.lpos1) then
|
||||
-- nvm.running, nvm.lastpos = teleport_player(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed)
|
||||
--elseif not teleport_mode then
|
||||
nvm.running, nvm.lastpos = move_nodes(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed, height)
|
||||
--end
|
||||
return nvm.running
|
||||
end
|
||||
|
||||
function flylib.reset_move(pos)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local height = techage.in_range(meta:contains("height") and meta:get_float("height") or 1, 0, 1)
|
||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||
|
||||
if nvm.running then return false end
|
||||
if meta:get_string("teleport_mode") == "enable" then return false end
|
||||
|
||||
if nvm.lpos1 and nvm.lpos1[1] then
|
||||
local move = vector.subtract(nvm.lpos1[1], (nvm.lastpos or nvm.lpos1)[1])
|
||||
|
||||
nvm.running, nvm.lastpos = move_nodes(pos, meta, nvm.lastpos or nvm.lpos1, move, max_speed, height)
|
||||
return nvm.running
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- pos is the controller block pos
|
||||
-- lpos is a list of node positions to be moved
|
||||
-- rot is one of "l", "r", "2l", "2r"
|
||||
function flylib.rotate_nodes(pos, lpos, rot)
|
||||
local meta = M(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
-- cpos is the center pos
|
||||
local cpos = meta:contains("center") and flylib.to_vector(meta:get_string("center"))
|
||||
local lpos2 = techage.rotate_around_center(lpos, rot, cpos)
|
||||
local param2
|
||||
local nodes2 = {}
|
||||
|
||||
techage.counting_add(owner, #lpos * 2)
|
||||
|
||||
for i, pos1 in ipairs(lpos) do
|
||||
local node = techage.get_node_lvm(pos1)
|
||||
if rot == "l" then
|
||||
param2 = techage.param2_turn_right(node.param2)
|
||||
elseif rot == "r" then
|
||||
param2 = techage.param2_turn_left(node.param2)
|
||||
else
|
||||
param2 = techage.param2_turn_right(techage.param2_turn_right(node.param2))
|
||||
end
|
||||
if not minetest.is_protected(pos1, owner) and is_simple_node(pos1) then
|
||||
minetest.remove_node(pos1)
|
||||
nodes2[#nodes2 + 1] = {pos = lpos2[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 lpos2
|
||||
end
|
||||
|
||||
function flylib.exchange_node(pos, name, param2)
|
||||
local meta = M(pos)
|
||||
local move_block
|
||||
|
||||
-- consider stored "objects"
|
||||
if meta:contains("ta_move_block") then
|
||||
move_block = meta:get_string("ta_move_block")
|
||||
end
|
||||
|
||||
minetest.swap_node(pos, {name = name, param2 = param2})
|
||||
|
||||
if move_block then
|
||||
meta:set_string("ta_move_block", move_block)
|
||||
end
|
||||
end
|
||||
|
||||
function flylib.remove_node(pos)
|
||||
local meta = M(pos)
|
||||
local move_block
|
||||
|
||||
-- consider stored "objects"
|
||||
if meta:contains("ta_move_block") then
|
||||
move_block = meta:get_string("ta_move_block")
|
||||
end
|
||||
|
||||
minetest.remove_node(pos)
|
||||
|
||||
if move_block then
|
||||
local node = minetest.deserialize(move_block)
|
||||
minetest.add_node(pos, node)
|
||||
meta:set_string("ta_move_block", "")
|
||||
end
|
||||
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)
|
||||
|
||||
techage.flylib = flylib
|
@ -1,52 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Keep only one formspec active per player
|
||||
|
||||
]]--
|
||||
|
||||
local P2S = minetest.pos_to_string
|
||||
|
||||
local ActiveFormspecs = {}
|
||||
local ActivePlayer = {}
|
||||
|
||||
|
||||
function techage.is_activeformspec(pos)
|
||||
return ActiveFormspecs[P2S(pos)]
|
||||
end
|
||||
|
||||
function techage.set_activeformspec(pos, player)
|
||||
local name = player and player:get_player_name()
|
||||
if name then
|
||||
if ActivePlayer[name] then
|
||||
ActiveFormspecs[ActivePlayer[name]] = nil
|
||||
end
|
||||
ActivePlayer[name] = P2S(pos)
|
||||
ActiveFormspecs[P2S(pos)] = true
|
||||
end
|
||||
end
|
||||
|
||||
function techage.reset_activeformspec(pos, player)
|
||||
local name = player and player:get_player_name()
|
||||
if name then
|
||||
if ActivePlayer[name] then
|
||||
ActiveFormspecs[ActivePlayer[name]] = nil
|
||||
ActivePlayer[name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if ActivePlayer[name] then
|
||||
ActiveFormspecs[ActivePlayer[name]] = nil
|
||||
ActivePlayer[name] = nil
|
||||
end
|
||||
end)
|
@ -1,197 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Oil fuel burning lib
|
||||
|
||||
]]--
|
||||
|
||||
local S2P = minetest.string_to_pos
|
||||
local P2S = minetest.pos_to_string
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
local ValidOilFuels = techage.firebox.ValidOilFuels
|
||||
local Burntime = techage.firebox.Burntime
|
||||
|
||||
techage.fuel = {}
|
||||
|
||||
local CAPACITY = 50
|
||||
local BLOCKING_TIME = 0.3 -- 300ms
|
||||
|
||||
techage.fuel.CAPACITY = CAPACITY
|
||||
|
||||
-- fuel burning categories (equal or better than...)
|
||||
techage.fuel.BT_BITUMEN = 5
|
||||
techage.fuel.BT_OIL = 4
|
||||
techage.fuel.BT_FUELOIL = 3
|
||||
techage.fuel.BT_NAPHTHA = 2
|
||||
techage.fuel.BT_GASOLINE = 1
|
||||
|
||||
|
||||
function techage.fuel.fuel_container(x, y, nvm)
|
||||
local itemname = ""
|
||||
if nvm.liquid and nvm.liquid.name and nvm.liquid.amount and nvm.liquid.amount > 0 then
|
||||
itemname = nvm.liquid.name.." "..nvm.liquid.amount
|
||||
end
|
||||
local fuel_percent = 0
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
fuel_percent = ((nvm.burn_cycles or 1) * 100) / (nvm.burn_cycles_total or 1)
|
||||
end
|
||||
return "container["..x..","..y.."]"..
|
||||
"box[0,0;1.05,2.1;#000000]"..
|
||||
"image[0.1,0.1;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
fuel_percent..":default_furnace_fire_fg.png]"..
|
||||
techage.item_image(0.1, 1.1, itemname)..
|
||||
"container_end[]"
|
||||
end
|
||||
|
||||
local function help(x, y)
|
||||
local tooltip = S("To add fuel punch\nthis block\nwith a fuel container")
|
||||
return "label["..x..","..y..";"..minetest.colorize("#000000", minetest.formspec_escape("[?]")).."]"..
|
||||
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
function techage.fuel.formspec(nvm)
|
||||
local title = S("Fuel Menu")
|
||||
return "size[4,3]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
|
||||
"label[1,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
help(3.4, -0.1)..
|
||||
techage.fuel.fuel_container(1.5, 1, nvm)
|
||||
end
|
||||
|
||||
function techage.fuel.can_dig(pos, player)
|
||||
if not player or minetest.is_protected(pos, player:get_player_name()) then
|
||||
return false
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
local inv = M(pos):get_inventory()
|
||||
return not inv or inv:is_empty("fuel") and nvm.liquid.amount == 0
|
||||
end
|
||||
|
||||
function techage.fuel.on_rightclick(pos, node, clicker)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
|
||||
end
|
||||
|
||||
-- name is the fuel item name
|
||||
function techage.fuel.burntime(name)
|
||||
if ValidOilFuels[name] then
|
||||
return Burntime[name] or 0.01 -- not zero !
|
||||
end
|
||||
return 0.01 -- not zero !
|
||||
end
|
||||
|
||||
-- equal or better than the given category (see 'techage.fuel.BT_BITUMEN,...')
|
||||
function techage.fuel.valid_fuel(name, category)
|
||||
return ValidOilFuels[name] and ValidOilFuels[name] <= category
|
||||
end
|
||||
|
||||
function techage.fuel.on_punch(pos, node, puncher, pointed_thing)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.blocking_time = mem.blocking_time or 0
|
||||
if mem.blocking_time > techage.SystemTime then
|
||||
return
|
||||
end
|
||||
|
||||
local wielded_item = puncher:get_wielded_item():get_name()
|
||||
local item_count = puncher:get_wielded_item():get_count()
|
||||
local new_item = techage.liquid.fill_on_punch(nvm, wielded_item, item_count, puncher)
|
||||
if new_item then
|
||||
puncher:set_wielded_item(new_item)
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm))
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
return
|
||||
end
|
||||
|
||||
local ldef = techage.liquid.get_liquid_def(wielded_item)
|
||||
if ldef and ValidOilFuels[ldef.inv_item] then
|
||||
local lqd = (minetest.registered_nodes[node.name] or {}).liquid
|
||||
if not lqd.fuel_cat or ValidOilFuels[ldef.inv_item] <= lqd.fuel_cat then
|
||||
local new_item = techage.liquid.empty_on_punch(pos, nvm, wielded_item, item_count)
|
||||
if new_item then
|
||||
puncher:set_wielded_item(new_item)
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm))
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function techage.fuel.get_fuel(nvm)
|
||||
if nvm.liquid and nvm.liquid.name and nvm.liquid.amount then
|
||||
if nvm.liquid.amount > 0 then
|
||||
nvm.liquid.amount = nvm.liquid.amount - 1
|
||||
return nvm.liquid.name
|
||||
end
|
||||
nvm.liquid.name = nil
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function techage.fuel.has_fuel(nvm)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
return nvm.liquid.amount > 0
|
||||
end
|
||||
|
||||
function techage.fuel.get_fuel_amount(nvm)
|
||||
if nvm.liquid and nvm.liquid.amount then
|
||||
return nvm.liquid.amount
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function techage.fuel.get_liquid_table(valid_fuel, capacity, start_firebox)
|
||||
return {
|
||||
capa = capacity,
|
||||
fuel_cat = valid_fuel,
|
||||
peek = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return liquid.srv_peek(nvm)
|
||||
end,
|
||||
put = function(pos, indir, name, amount)
|
||||
if techage.fuel.valid_fuel(name, valid_fuel) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local res = liquid.srv_put(nvm, name, amount, capacity)
|
||||
start_firebox(pos, nvm)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
|
||||
end
|
||||
return res
|
||||
end
|
||||
return amount
|
||||
end,
|
||||
take = function(pos, indir, name, amount)
|
||||
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", techage.fuel.formspec(nvm))
|
||||
end
|
||||
return amount, name
|
||||
end,
|
||||
untake = function(pos, indir, name, amount)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local leftover = liquid.srv_put(nvm, name, amount, capacity)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
}
|
||||
end
|
@ -1,102 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Gravel Sieve basis functions
|
||||
|
||||
]]--
|
||||
|
||||
-- Increase the probability over the natural occurrence
|
||||
local PROBABILITY_FACTOR = 2
|
||||
|
||||
-- Ore probability table (1/n)
|
||||
local ore_probability = {
|
||||
}
|
||||
|
||||
local ProbabilityCorrections = {
|
||||
["default:tin_lump"] = 0.3, -- extensively used
|
||||
["default:coal_lump"] = 0.2, -- extensively used
|
||||
["default:iron_lump"] = 0.5, -- extensively used
|
||||
["techage:baborium_lump"] = 99999, -- mining required
|
||||
}
|
||||
|
||||
-- collect all registered ores and calculate the probability
|
||||
local function add_ores()
|
||||
for _,item in pairs(minetest.registered_ores) do
|
||||
if not ore_probability[item.ore] and minetest.registered_nodes[item.ore] then
|
||||
local drop = minetest.registered_nodes[item.ore].drop
|
||||
if type(drop) == "string"
|
||||
and drop ~= item.ore
|
||||
and drop ~= ""
|
||||
and item.ore_type == "scatter"
|
||||
and item.wherein == "default:stone"
|
||||
and item.clust_scarcity ~= nil and item.clust_scarcity > 0
|
||||
and item.clust_num_ores ~= nil and item.clust_num_ores > 0
|
||||
and item.y_max ~= nil and item.y_min ~= nil then
|
||||
local factor = 0.5
|
||||
if item.y_max < -250 then
|
||||
factor = -250 / item.y_max
|
||||
end
|
||||
local probability = (techage.ore_rarity / PROBABILITY_FACTOR) * item.clust_scarcity /
|
||||
(item.clust_num_ores * factor)
|
||||
-- lower value means higher probability
|
||||
ore_probability[drop] = math.min(ore_probability[drop] or 100000, probability)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- some corrections
|
||||
for key, correction in pairs(ProbabilityCorrections) do
|
||||
if ore_probability[key] then
|
||||
ore_probability[key] = ore_probability[key] * correction
|
||||
-- consider upper and lower level
|
||||
ore_probability[key] = techage.in_range(ore_probability[key], 10, 100000)
|
||||
end
|
||||
end
|
||||
local overall_probability = 0.0
|
||||
for name,probability in pairs(ore_probability) do
|
||||
minetest.log("info", string.format("[techage] %-32s %u", name, probability))
|
||||
overall_probability = overall_probability + 1.0/probability
|
||||
end
|
||||
minetest.log("info", string.format("[techage] Overall probability %g", overall_probability))
|
||||
end
|
||||
|
||||
minetest.register_on_mods_loaded(add_ores)
|
||||
|
||||
--
|
||||
-- Change the probability of ores or register new ores for sieving
|
||||
--
|
||||
function techage.register_ore_for_gravelsieve(ore_name, probability)
|
||||
ore_probability[ore_name] = probability
|
||||
end
|
||||
|
||||
-- determine ore based on the calculated probability
|
||||
function techage.gravelsieve_get_random_gravel_ore()
|
||||
for ore, probability in pairs(ore_probability) do
|
||||
if math.random(probability) == 1 then
|
||||
return ItemStack(ore)
|
||||
end
|
||||
end
|
||||
if math.random(2) == 1 then
|
||||
return ItemStack("default:gravel")
|
||||
else
|
||||
return ItemStack("techage:sieved_gravel")
|
||||
end
|
||||
end
|
||||
|
||||
function techage.gravelsieve_get_random_basalt_ore()
|
||||
if math.random(40) == 1 then
|
||||
return ItemStack("default:coal_lump")
|
||||
elseif math.random(40) == 1 then
|
||||
return ItemStack("default:iron_lump")
|
||||
elseif math.random(2) == 1 then
|
||||
return ItemStack("techage:basalt_gravel")
|
||||
else
|
||||
return ItemStack("techage:sieved_basalt_gravel")
|
||||
end
|
||||
end
|
@ -1,240 +0,0 @@
|
||||
--[[
|
||||
|
||||
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)
|
||||
if Stations and Stations.get_node_table then
|
||||
local tbl = {M(pos):get_string("remote_name")}
|
||||
for key,item in pairs(Stations:get_node_table(pos) or {}) 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
|
||||
return {}
|
||||
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)
|
||||
if pos then
|
||||
local owner = M(pos):get_string("owner")
|
||||
return table.concat(get_free_server_list(pos, owner), ",") or ""
|
||||
end
|
||||
return ""
|
||||
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 or 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
|
@ -1,146 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
GPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Laser basis functions
|
||||
|
||||
]]--
|
||||
|
||||
local Entities = {}
|
||||
local SIZES = {1, 2, 3, 6, 12, 24, 48} -- for laser entities
|
||||
local GAP_MIN = 1 -- between 2 blocks
|
||||
local GAP_MAX = 2 * 48 -- between 2 blocks
|
||||
|
||||
-- Return the area (pos1,pos2) for a destination node
|
||||
local function get_pos_range(pos, dir)
|
||||
local pos1 = vector.add(pos, vector.multiply(dir, GAP_MIN + 1)) -- min
|
||||
local pos2 = vector.add(pos, vector.multiply(dir, GAP_MAX + 1)) -- max
|
||||
return pos1, pos2
|
||||
end
|
||||
|
||||
-- Return first pos after start pos and the destination pos
|
||||
local function get_positions(pos, mem, dir)
|
||||
local pos1 = vector.add(pos, dir) -- start pos
|
||||
local _, pos2 = get_pos_range(pos, dir) -- last pos
|
||||
local _, pos3 = minetest.line_of_sight(pos1, pos2)
|
||||
pos3 = pos3 or pos2 -- destination node pos
|
||||
if not mem.peer_node_pos or not vector.equals(pos3, mem.peer_node_pos) then
|
||||
mem.peer_node_pos = pos3
|
||||
local dist = vector.distance(pos1, pos3)
|
||||
if dist > GAP_MIN and dist <= GAP_MAX then
|
||||
return true, pos1, pos3 -- new values
|
||||
else
|
||||
return false -- invalid values
|
||||
end
|
||||
end
|
||||
return true -- no new values
|
||||
end
|
||||
|
||||
-- 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)
|
||||
|
||||
for _, size in ipairs(SIZES) do
|
||||
if dist <= (size * 2) then
|
||||
pos1 = vector.add (pos1, vector.multiply(dir, (size / 2) - 0.5))
|
||||
pos2 = vector.subtract(pos2, vector.multiply(dir, (size / 2) + 0.5))
|
||||
return size, pos1, pos2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function del_laser(pos)
|
||||
local key = minetest.hash_node_position(pos)
|
||||
local items = Entities[key]
|
||||
if items then
|
||||
local laser1, laser2 = items[1], items[2]
|
||||
laser1:remove()
|
||||
laser2:remove()
|
||||
Entities[key] = nil
|
||||
end
|
||||
return key
|
||||
end
|
||||
|
||||
local function add_laser(pos, pos1, pos2, size, param2)
|
||||
local key = del_laser(pos)
|
||||
|
||||
local laser1 = minetest.add_entity(pos1, "techage:laser" .. size)
|
||||
if laser1 then
|
||||
local yaw = math.pi / 2 * (param2 + 1)
|
||||
laser1:set_rotation({x = 0, y = yaw, z = 0})
|
||||
end
|
||||
|
||||
local laser2 = minetest.add_entity(pos2, "techage:laser" .. size)
|
||||
if laser2 then
|
||||
param2 = (param2 + 2) % 4 -- flip dir
|
||||
local yaw = math.pi / 2 * (param2 + 1)
|
||||
laser2:set_rotation({x = 0, y = yaw, z = 0})
|
||||
end
|
||||
|
||||
Entities[key] = {laser1, laser2}
|
||||
end
|
||||
|
||||
for _, size in ipairs(SIZES) do
|
||||
minetest.register_entity("techage:laser" .. size, {
|
||||
initial_properties = {
|
||||
visual = "cube",
|
||||
textures = {
|
||||
"techage_laser.png",
|
||||
"techage_laser.png",
|
||||
"techage_laser.png",
|
||||
"techage_laser.png",
|
||||
"techage_laser.png",
|
||||
"techage_laser.png",
|
||||
},
|
||||
use_texture_alpha = true,
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
pointable = false,
|
||||
static_save = false,
|
||||
visual_size = {x = size, y = 0.05, z = 0.05},
|
||||
glow = 14,
|
||||
shaded = true,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------------------
|
||||
-- if force is not true, do not redraw the laser if nothing has changed
|
||||
function techage.renew_laser(pos, force)
|
||||
local mem = techage.get_mem(pos)
|
||||
if force then
|
||||
mem.peer_node_pos = nil
|
||||
mem.param2 = nil
|
||||
end
|
||||
mem.param2 = mem.param2 or minetest.get_node(pos).param2
|
||||
local dir = minetest.facedir_to_dir(mem.param2)
|
||||
local res, pos1, pos2 = get_positions(pos, mem, dir)
|
||||
if pos1 then
|
||||
local size, pos3, pos4 = get_laser_length_and_pos(pos1, pos2, dir)
|
||||
if size then
|
||||
add_laser(pos, pos3, pos4, size, mem.param2)
|
||||
return res, pos1, pos2
|
||||
end
|
||||
end
|
||||
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
|
@ -1,25 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
For the transition from v0.26 to v1.0
|
||||
|
||||
]]--
|
||||
|
||||
function techage.register_node_for_v1_transition(nodenames, on_node_load)
|
||||
minetest.register_lbm({
|
||||
label = "[TechAge] V1 transition",
|
||||
name = nodenames[1].."transition",
|
||||
nodenames = nodenames,
|
||||
run_at_every_load = false,
|
||||
action = function(pos, node)
|
||||
on_node_load(pos, node)
|
||||
end
|
||||
})
|
||||
end
|
@ -1,633 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Helper functions
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Input data to generate the Param2ToDir table
|
||||
local Input = {
|
||||
8,9,10,11, -- 1
|
||||
16,17,18,19, -- 2
|
||||
4,5,6,7, -- 3
|
||||
12,13,14,15, -- 4
|
||||
0,1,2,3, -- 5
|
||||
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] or FACEDIR_TO_ROT[0]
|
||||
end
|
||||
|
||||
function techage.param2_turn_left(param2)
|
||||
return (RotationViaYAxis[param2] or RotationViaYAxis[0])[2]
|
||||
end
|
||||
|
||||
function techage.param2_turn_right(param2)
|
||||
return (RotationViaYAxis[param2] or RotationViaYAxis[0])[1]
|
||||
end
|
||||
|
||||
-- Roll a block in north direction (south is vice versa)
|
||||
local RollNorth = {
|
||||
{0,4,22,8},
|
||||
{1,5,23,9},
|
||||
{2,6,20,10},
|
||||
{3,7,21,11},
|
||||
{12,13,14,15},
|
||||
{16,19,18,17},
|
||||
}
|
||||
-- Roll a block in east direction (west is vice versa)
|
||||
local RollEast = {
|
||||
{0,12,20,16},
|
||||
{1,13,21,17},
|
||||
{2,14,22,18},
|
||||
{3,15,23,19},
|
||||
{4,7,6,5},
|
||||
{8,9,10,11},
|
||||
}
|
||||
|
||||
-- Generate a table for all facedir and param2 values:
|
||||
-- TurnUp[facedir][param2] = new_param2
|
||||
local TurnUp = {[0] = {}, {}, {}, {}}
|
||||
|
||||
for i = 1,6 do
|
||||
for j = 1,4 do
|
||||
local idx = RollNorth[i][j]
|
||||
TurnUp[0][idx] = RollNorth[i][j == 4 and 1 or j + 1] -- north
|
||||
TurnUp[2][idx] = RollNorth[i][j == 1 and 4 or j - 1] -- south
|
||||
|
||||
idx = RollEast[i][j]
|
||||
TurnUp[1][idx] = RollEast[i][j == 4 and 1 or j + 1] -- east
|
||||
TurnUp[3][idx] = RollEast[i][j == 1 and 4 or j - 1] -- west
|
||||
end
|
||||
end
|
||||
|
||||
-- facedir is from the players (0..3)
|
||||
-- param2 is from the node (0..23)
|
||||
function techage.param2_turn_up(facedir, param2)
|
||||
return TurnUp[facedir % 4][param2 % 24]
|
||||
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
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Helper functions
|
||||
-------------------------------------------------------------------------------
|
||||
-- allowed for digging
|
||||
local SimpleNodes = {}
|
||||
|
||||
-- translation from param2 to dir (out of the node upwards)
|
||||
local Param2Dir = {}
|
||||
for idx,val in ipairs(Input) do
|
||||
Param2Dir[val] = math.floor((idx - 1) / 4) + 1
|
||||
end
|
||||
|
||||
-- used by lamps and power switches
|
||||
function techage.determine_node_bottom_as_dir(node)
|
||||
return tubelib2.Turn180Deg[Param2Dir[node.param2] or 1]
|
||||
end
|
||||
|
||||
function techage.determine_node_top_as_dir(node)
|
||||
return Param2Dir[node.param2] or 1
|
||||
end
|
||||
|
||||
-- rotation rules (screwdriver) for wallmounted "facedir" nodes
|
||||
function techage.rotate_wallmounted(param2)
|
||||
local offs = math.floor(param2 / 4) * 4
|
||||
local rot = ((param2 % 4) + 1) % 4
|
||||
return offs + rot
|
||||
end
|
||||
|
||||
function techage.in_range(val, min, max)
|
||||
val = tonumber(val)
|
||||
if val < min then return min end
|
||||
if val > max then return max end
|
||||
return val
|
||||
end
|
||||
|
||||
function techage.one_of(val, selection)
|
||||
for _,v in ipairs(selection) do
|
||||
if val == v then return val end
|
||||
end
|
||||
return selection[1]
|
||||
end
|
||||
|
||||
function techage.index(list, x)
|
||||
for idx, v in pairs(list) do
|
||||
if v == x then return idx end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function techage.in_list(list, x)
|
||||
for idx, v in pairs(list) do
|
||||
if v == x then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function techage.add_to_set(set, x)
|
||||
if not techage.index(set, x) then
|
||||
table.insert(set, x)
|
||||
end
|
||||
end
|
||||
|
||||
-- techage.tbl_filter({"a", "b", "c", "d"}, function(v, k, t) return v >= "c" end) --> {"c","d"}
|
||||
techage.tbl_filter = function(t, filterIter)
|
||||
local out = {}
|
||||
|
||||
for k, v in pairs(t) do
|
||||
if filterIter(v, k, t) then out[k] = v end
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
function techage.get_node_lvm(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then
|
||||
return node
|
||||
end
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
|
||||
local data = vm:get_data()
|
||||
local param2_data = vm:get_param2_data()
|
||||
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local idx = area:indexp(pos)
|
||||
if data[idx] and param2_data[idx] then
|
||||
return {
|
||||
name = minetest.get_name_from_content_id(data[idx]),
|
||||
param2 = param2_data[idx]
|
||||
}
|
||||
end
|
||||
return {name="ignore", param2=0}
|
||||
end
|
||||
|
||||
function techage.is_air_like(name)
|
||||
local ndef = minetest.registered_nodes[name]
|
||||
if ndef and ndef.buildable_to then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- returns true, if node can be dug, otherwise false
|
||||
function techage.can_dig_node(name, ndef)
|
||||
if not ndef then return false end
|
||||
if SimpleNodes[name] ~= nil then
|
||||
return SimpleNodes[name]
|
||||
end
|
||||
|
||||
if ndef.groups and ndef.groups.techage_door == 1 then
|
||||
SimpleNodes[name] = true
|
||||
return true
|
||||
end
|
||||
if name == "ignore" then
|
||||
SimpleNodes[name] = false
|
||||
return false
|
||||
end
|
||||
if name == "air" then
|
||||
SimpleNodes[name] = true
|
||||
return true
|
||||
end
|
||||
if ndef.buildable_to == true then
|
||||
SimpleNodes[name] = true
|
||||
return true
|
||||
end
|
||||
-- don't remove nodes with some intelligence or undiggable nodes
|
||||
if ndef.drop == "" then
|
||||
SimpleNodes[name] = false
|
||||
return false
|
||||
end
|
||||
if ndef.diggable == false then
|
||||
SimpleNodes[name] = false
|
||||
return false
|
||||
end
|
||||
if ndef.after_dig_node then
|
||||
SimpleNodes[name] = false
|
||||
return false
|
||||
end
|
||||
-- add it to the white list
|
||||
SimpleNodes[name] = true
|
||||
return true
|
||||
end
|
||||
|
||||
-- Simple nodes
|
||||
function techage.register_simple_nodes(node_names, is_valid)
|
||||
if is_valid == nil then is_valid = true end
|
||||
for _,name in ipairs(node_names or {}) do
|
||||
SimpleNodes[name] = is_valid
|
||||
end
|
||||
end
|
||||
|
||||
techage.dig_states = {
|
||||
NOT_DIGGABLE = 1,
|
||||
INV_FULL = 2,
|
||||
DUG = 3
|
||||
}
|
||||
|
||||
-- Digs a node like a player would by utilizing a fake player object.
|
||||
-- add_to_inv(itemstacks) is a method that should try to add the dropped stacks to an appropriate inventory.
|
||||
-- The node will only be dug, if add_to_inv(itemstacks) returns true.
|
||||
function techage.dig_like_player(pos, fake_player, add_to_inv)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
local ndef = minetest.registered_nodes[node.name]
|
||||
if not ndef or ndef.diggable == false or (ndef.can_dig and not ndef.can_dig(pos, fake_player)) then
|
||||
return techage.dig_states.NOT_DIGGABLE
|
||||
end
|
||||
local drop_as_strings = minetest.get_node_drops(node)
|
||||
local drop_as_stacks = {}
|
||||
for _,itemstring in ipairs(drop_as_strings) do
|
||||
drop_as_stacks[#drop_as_stacks+1] = ItemStack(itemstring)
|
||||
end
|
||||
local meta = M(pos)
|
||||
if ndef.preserve_metadata then
|
||||
ndef.preserve_metadata(pos, node, meta, drop_as_stacks)
|
||||
end
|
||||
|
||||
if add_to_inv(drop_as_stacks) then
|
||||
local oldmeta = meta:to_table()
|
||||
minetest.remove_node(pos)
|
||||
|
||||
if ndef.after_dig_node then
|
||||
ndef.after_dig_node(pos, node, oldmeta, fake_player)
|
||||
end
|
||||
return techage.dig_states.DUG
|
||||
end
|
||||
return techage.dig_states.INV_FULL
|
||||
end
|
||||
|
||||
local function handle_drop(drop)
|
||||
-- To keep it simple, return only the item with the lowest rarity
|
||||
if drop.items then
|
||||
local rarity = 9999
|
||||
local name
|
||||
for idx,item in ipairs(drop.items) do
|
||||
if item.rarity and item.rarity < rarity then
|
||||
rarity = item.rarity
|
||||
name = item.items[1] -- take always the first item
|
||||
else
|
||||
return item.items[1] -- take always the first item
|
||||
end
|
||||
end
|
||||
return name
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- returns the node name, if node can be dropped, otherwise nil
|
||||
function techage.dropped_node(node, ndef)
|
||||
if node.name == "air" then return end
|
||||
--if ndef.buildable_to == true then return end
|
||||
if not ndef.diggable then return end
|
||||
if ndef.drop == "" then return end
|
||||
if type(ndef.drop) == "table" then
|
||||
return handle_drop(ndef.drop)
|
||||
end
|
||||
return ndef.drop or node.name
|
||||
end
|
||||
|
||||
-- needed for windmill plants
|
||||
local function determine_ocean_ids()
|
||||
techage.OceanIdTbl = {}
|
||||
for name, _ in pairs(minetest.registered_biomes) do
|
||||
if string.find(name, "ocean") then
|
||||
local id = minetest.get_biome_id(name)
|
||||
--print(id, name)
|
||||
techage.OceanIdTbl[id] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
determine_ocean_ids()
|
||||
|
||||
-- check if natural water is on given position (water placed by player has param2 = 1)
|
||||
function techage.is_ocean(pos)
|
||||
if pos.y > 1 then return false end
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name ~= "default:water_source" then return false end
|
||||
if node.param2 == 1 then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
function techage.item_image(x, y, itemname, count)
|
||||
local name, size = unpack(string.split(itemname, " "))
|
||||
size = count and count or size
|
||||
size = tonumber(size) or 1
|
||||
local label = ""
|
||||
local text = minetest.formspec_escape(ItemStack(itemname):get_description())
|
||||
local tooltip = "tooltip["..x..","..y..";1,1;"..text..";#0C3D32;#FFFFFF]"
|
||||
|
||||
if minetest.registered_tools[name] and size > 1 then
|
||||
local offs = 0
|
||||
if size < 10 then
|
||||
offs = 0.65
|
||||
elseif size < 100 then
|
||||
offs = 0.5
|
||||
elseif size < 1000 then
|
||||
offs = 0.35
|
||||
else
|
||||
offs = 0.2
|
||||
end
|
||||
label = "label["..(x + offs)..","..(y + 0.45)..";"..tostring(size).."]"
|
||||
end
|
||||
|
||||
return "box["..x..","..y..";0.85,0.9;#808080]"..
|
||||
"item_image["..x..","..y..";1,1;"..itemname.."]"..
|
||||
tooltip..
|
||||
label
|
||||
end
|
||||
|
||||
function techage.item_image_small(x, y, itemname, tooltip_prefix)
|
||||
local name = unpack(string.split(itemname, " "))
|
||||
local tooltip = ""
|
||||
local ndef = minetest.registered_nodes[name] or minetest.registered_items[name] or minetest.registered_craftitems[name]
|
||||
|
||||
if ndef and ndef.description then
|
||||
local text = minetest.formspec_escape(ndef.description)
|
||||
tooltip = "tooltip["..x..","..y..";0.8,0.8;"..tooltip_prefix..": "..text..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
return "box["..x..","..y..";0.65,0.7;#808080]"..
|
||||
"item_image["..x..","..y..";0.8,0.8;"..name.."]"..
|
||||
tooltip
|
||||
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
|
||||
return "label["..x..",-0.1;"..minetest.colorize("#000000", minetest.formspec_escape("[?]")).."]"..
|
||||
"tooltip["..x..",-0.1;0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
function techage.wrench_tooltip(x, y)
|
||||
local tooltip = S("Block has an\nadditional wrench menu")
|
||||
return "image["..x.."," .. y .. ";0.5,0.5;techage_inv_wrench.png]" ..
|
||||
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
techage.RegisteredMobsMods = {}
|
||||
|
||||
-- Register mobs mods for the move/fly controllers
|
||||
function techage.register_mobs_mods(mod)
|
||||
techage.RegisteredMobsMods[mod] = true
|
||||
end
|
||||
|
||||
function techage.beduino_signed_var(val)
|
||||
val = val or 0
|
||||
return val >= 32768 and val - 0x10000 or val
|
||||
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
|
||||
|
||||
-- Delete number with: `//lua minetest.get_player_by_name("<name>"):get_meta():set_string("techage_collider_number", "")`
|
||||
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Scheduler for a table-based, cyclic call of functions
|
||||
-------------------------------------------------------------------------------
|
||||
local TABLE_SIZE = 256
|
||||
techage.scheduler = {}
|
||||
|
||||
local function add_to_table(tbl, i, func)
|
||||
while i < TABLE_SIZE do
|
||||
if not tbl[i] then
|
||||
tbl[i] = func
|
||||
return i + 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
function techage.scheduler.init(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.sched_idx = 0
|
||||
end
|
||||
|
||||
-- tFunc : (empty) table of functions
|
||||
-- call_rate : (2,4,8,16,32,64 or 128)
|
||||
-- offset : 0-128
|
||||
-- func : function to be called
|
||||
function techage.scheduler.register(tFunc, call_rate, offset, func)
|
||||
local i= 0
|
||||
while i < TABLE_SIZE do
|
||||
if (i % call_rate) == offset then
|
||||
i = add_to_table(tFunc, i, func)
|
||||
else
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
return tFunc
|
||||
end
|
||||
|
||||
-- tFunc : table of functions
|
||||
-- default : default function (optional)
|
||||
-- Returns a function to be called be the callee
|
||||
function techage.scheduler.get(pos, tFunc, default)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.sched_idx = ((mem.sched_idx or 0) + 1) % TABLE_SIZE
|
||||
return tFunc[mem.sched_idx] or default or function() end
|
||||
end
|
@ -1,278 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Liquid lib
|
||||
|
||||
]]--
|
||||
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local P2S = minetest.pos_to_string
|
||||
local LQD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).liquid end
|
||||
|
||||
local BLOCKING_TIME = 0.3 -- 300ms
|
||||
|
||||
techage.liquid = {}
|
||||
local LiquidDef = {}
|
||||
local IsLiquid = {}
|
||||
local ContainerDef = {}
|
||||
|
||||
local function help(x, y)
|
||||
local tooltip = S("To add liquids punch\nthe tank\nwith a liquid container")
|
||||
return "label["..x..","..y..";"..minetest.colorize("#000000", minetest.formspec_escape("[?]")).."]"..
|
||||
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
local name = minetest.get_node(pos).name
|
||||
if name == "techage:ta4_tank" then
|
||||
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[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[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
|
||||
|
||||
function techage.liquid.is_empty(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return not nvm.liquid or (nvm.liquid.amount or 0) <= 0
|
||||
end
|
||||
|
||||
techage.liquid.recv_message = {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "load" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
return techage.power.percent(LQD(pos).capa, nvm.liquid.amount), nvm.liquid.amount
|
||||
elseif topic == "size" then
|
||||
return LQD(pos).capa
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == 128 then
|
||||
return 0, techage.get_node_lvm(pos).name
|
||||
elseif topic == 134 then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
if payload[1] == 1 then
|
||||
local value = techage.power.percent(LQD(pos).capa, nvm.liquid.amount)
|
||||
return 0, {math.floor(value + 0.5)}
|
||||
else
|
||||
return 0, {nvm.liquid.amount}
|
||||
end
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
-- like: register_liquid("techage:ta3_barrel_oil", "techage:ta3_barrel_empty", 10, "techage:oil")
|
||||
function techage.register_liquid(full_container, empty_container, container_size, inv_item)
|
||||
LiquidDef[full_container] = {container = empty_container, size = container_size, inv_item = inv_item}
|
||||
ContainerDef[empty_container] = ContainerDef[empty_container] or {}
|
||||
ContainerDef[empty_container][inv_item] = full_container
|
||||
IsLiquid[inv_item] = true
|
||||
if inv_item == "techage:water" and container_size == 1 then
|
||||
techage.register_water_bucket(empty_container, full_container)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_liquid_def(full_container)
|
||||
return LiquidDef[full_container]
|
||||
end
|
||||
|
||||
local function get_container_def(container_name)
|
||||
return ContainerDef[container_name]
|
||||
end
|
||||
|
||||
local function is_container_empty(container_name)
|
||||
return ContainerDef[container_name]
|
||||
end
|
||||
|
||||
local function get_full_container(empty_container, inv_item)
|
||||
return ContainerDef[empty_container] and ContainerDef[empty_container][inv_item]
|
||||
end
|
||||
|
||||
-- used by filler
|
||||
local function fill_container(pos, inv, empty_container)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
local full_container = get_full_container(empty_container, nvm.liquid.name)
|
||||
if empty_container and full_container then
|
||||
local ldef = get_liquid_def(full_container)
|
||||
if ldef and nvm.liquid.amount - ldef.size >= 0 then
|
||||
if inv:room_for_item("dst", {name = full_container}) then
|
||||
inv:add_item("dst", {name = full_container})
|
||||
nvm.liquid.amount = nvm.liquid.amount - ldef.size
|
||||
if nvm.liquid.amount == 0 then
|
||||
nvm.liquid.name = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- undo
|
||||
inv:add_item("src", {name = empty_container})
|
||||
return false
|
||||
end
|
||||
|
||||
-- used by filler
|
||||
local function empty_container(pos, inv, full_container)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
local ndef_lqd = LQD(pos)
|
||||
local tank_size = (ndef_lqd and ndef_lqd.capa) or 0
|
||||
local ldef = get_liquid_def(full_container)
|
||||
if ldef and (not nvm.liquid.name or ldef.inv_item == nvm.liquid.name) then
|
||||
if nvm.liquid.amount + ldef.size <= tank_size then
|
||||
if inv:room_for_item("dst", {name = ldef.container}) then
|
||||
inv:add_item("dst", {name = ldef.container})
|
||||
nvm.liquid.amount = nvm.liquid.amount + ldef.size
|
||||
nvm.liquid.name = ldef.inv_item
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- undo
|
||||
inv:add_item("src", {name = full_container})
|
||||
return false
|
||||
end
|
||||
|
||||
-- check if the wielded empty container can be replaced by a full
|
||||
-- container and added to the players inventory
|
||||
local function fill_on_punch(nvm, empty_container, item_count, puncher)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
local full_container = get_full_container(empty_container, nvm.liquid.name)
|
||||
if empty_container and full_container then
|
||||
local item = {name = full_container}
|
||||
local ldef = get_liquid_def(full_container)
|
||||
if ldef and nvm.liquid.amount - ldef.size >= 0 then
|
||||
if item_count > 1 then -- can't be simply replaced?
|
||||
-- check for extra free space
|
||||
local inv = puncher:get_inventory()
|
||||
if inv:room_for_item("main", {name = full_container}) then
|
||||
-- add full container and return
|
||||
-- the empty once - 1
|
||||
inv:add_item("main", {name = full_container})
|
||||
item = {name = empty_container, count = item_count - 1}
|
||||
else
|
||||
return -- no free space
|
||||
end
|
||||
end
|
||||
nvm.liquid.amount = nvm.liquid.amount - ldef.size
|
||||
if nvm.liquid.amount == 0 then
|
||||
nvm.liquid.name = nil
|
||||
end
|
||||
return item -- to be added to the players inv.
|
||||
end
|
||||
elseif nvm.liquid.name and not IsLiquid[nvm.liquid.name] then
|
||||
if empty_container == "" then
|
||||
local count = math.max(nvm.liquid.amount, 99)
|
||||
local name = nvm.liquid.name
|
||||
nvm.liquid.amount = nvm.liquid.amount - count
|
||||
if nvm.liquid.amount == 0 then
|
||||
nvm.liquid.name = nil
|
||||
end
|
||||
return {name = name, count = count}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function legacy_items(full_container, item_count)
|
||||
if full_container == "techage:isobutane" then
|
||||
return {container = "", size = item_count, inv_item = full_container}
|
||||
elseif full_container == "techage:oil_source" then
|
||||
return {container = "", size = item_count, inv_item = full_container}
|
||||
end
|
||||
end
|
||||
|
||||
-- check if the wielded full container can be emptied into the tank
|
||||
local function empty_on_punch(pos, nvm, full_container, item_count)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
nvm.liquid.amount = nvm.liquid.amount or 0
|
||||
local lqd_def = get_liquid_def(full_container) or legacy_items(full_container, item_count)
|
||||
local ndef_lqd = LQD(pos)
|
||||
if lqd_def and ndef_lqd then
|
||||
local tank_size = ndef_lqd.capa or 0
|
||||
if not nvm.liquid.name or lqd_def.inv_item == nvm.liquid.name then
|
||||
if nvm.liquid.amount + lqd_def.size <= tank_size then
|
||||
nvm.liquid.amount = nvm.liquid.amount + lqd_def.size
|
||||
nvm.liquid.name = lqd_def.inv_item
|
||||
return {name = lqd_def.container}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function techage.liquid.on_punch(pos, node, puncher, pointed_thing)
|
||||
local public = M(pos):get_int("public") == 1
|
||||
if not public and minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.blocking_time = mem.blocking_time or 0
|
||||
if mem.blocking_time > techage.SystemTime then
|
||||
return
|
||||
end
|
||||
|
||||
local wielded_item = puncher:get_wielded_item():get_name()
|
||||
local item_count = puncher:get_wielded_item():get_count()
|
||||
local new_item = fill_on_punch(nvm, wielded_item, item_count, puncher)
|
||||
or empty_on_punch(pos, nvm, wielded_item, item_count)
|
||||
if new_item then
|
||||
puncher:set_wielded_item(new_item)
|
||||
M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm))
|
||||
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function techage.liquid.get_liquid_amount(nvm)
|
||||
if nvm.liquid and nvm.liquid.amount then
|
||||
return nvm.liquid.amount
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
techage.liquid.get_liquid_def = get_liquid_def
|
||||
techage.liquid.get_container_def = get_container_def
|
||||
techage.liquid.is_container_empty = is_container_empty
|
||||
techage.liquid.get_full_container = get_full_container
|
||||
techage.liquid.fill_container = fill_container
|
||||
techage.liquid.empty_container = empty_container
|
||||
techage.liquid.fill_on_punch = fill_on_punch
|
||||
techage.liquid.empty_on_punch = empty_on_punch
|
@ -1,91 +0,0 @@
|
||||
techage.manual_DE = {}
|
||||
|
||||
techage.manual_DE.aTitel = {
|
||||
"1,SaferLua Controller with Periphery",
|
||||
"2,SaferLua Controller",
|
||||
"3,Central Server",
|
||||
"3,SaferLua Controller Terminal",
|
||||
}
|
||||
|
||||
techage.manual_DE.aText = {
|
||||
"",
|
||||
|
||||
"The SaferLua Controller is a small computer programmable in Lua to control your machinery.\n"..
|
||||
|
||||
"In contrast to the SmartLine Controller this controller allows to implement larger and smarter control and monitoring tasks.\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
"The controller can be programmed in SaferLua a subset of Lua for safe and secure Lua programs the Minetest server.\n"..
|
||||
|
||||
"\n",
|
||||
|
||||
"The Server node can be placed everywhere. It can also be used for communication purposes between several Controllers.\n"..
|
||||
|
||||
"The Server has a form to enter valid usernames for server access.\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
"The controller has a menu form with the following tabs:\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
" - the 'init' tab for the initialization code block\n"..
|
||||
|
||||
" - the 'func' tab for the Lua functions\n"..
|
||||
|
||||
" - the 'loop' tab for the main code block\n"..
|
||||
|
||||
" - the 'outp' tab for debugging outputs via '$print()'\n"..
|
||||
|
||||
" - the 'notes' tab for your code snippets or other notes\n"..
|
||||
|
||||
" - the 'help' tab with information to the available commands\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
"The controller needs battery power to work.\n"..
|
||||
|
||||
"\n",
|
||||
|
||||
"The Terminal is used to send command strings to the controller.\n"..
|
||||
|
||||
"In turn\\, the controller can send text strings to the terminal.\n"..
|
||||
|
||||
"The Terminal has a help system for internal commands. Its supports the following commands:\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
" - 'clear' = clear the screen\n"..
|
||||
|
||||
" - 'help' = output this message\n"..
|
||||
|
||||
" - 'pub' = switch terminal to public use (everybody can enter commands)\n"..
|
||||
|
||||
" - 'priv' = switch terminal to private use (only the owner can enter commands)\n"..
|
||||
|
||||
" - 'send <num> on/off' = send on/off event to e. g. lamps (for testing purposes)\n"..
|
||||
|
||||
" - 'msg <num> <text>' = send a text message to another Controller (for testing purposes)\n"..
|
||||
|
||||
"\n"..
|
||||
|
||||
"\n",
|
||||
|
||||
}
|
||||
|
||||
techage.manual_DE.aItemName = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
|
||||
techage.manual_DE.aPlanTable = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
mark.lua:
|
||||
|
||||
]]--
|
||||
|
||||
local marker_region = {}
|
||||
|
||||
function techage.unmark_region(name)
|
||||
if marker_region[name] ~= nil then --marker already exists
|
||||
--wip: make the area stay loaded somehow
|
||||
for _, entity in ipairs(marker_region[name]) do
|
||||
entity:remove()
|
||||
end
|
||||
marker_region[name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function techage.mark_region(name, pos1, pos2, owner, secs)
|
||||
|
||||
if not name or not pos1 or not pos2 then return end
|
||||
|
||||
techage.unmark_region(name)
|
||||
|
||||
local thickness = 0.2
|
||||
local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2
|
||||
local markers = {}
|
||||
|
||||
--XY plane markers
|
||||
for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do
|
||||
local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "techage:region_cube")
|
||||
if marker ~= nil then
|
||||
marker:set_properties({
|
||||
visual_size={x=sizex * 2, y=sizey * 2},
|
||||
--collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness},
|
||||
collisionbox = {0,0,0, 0,0,0},
|
||||
})
|
||||
if owner then
|
||||
marker:set_nametag_attributes({text = owner})
|
||||
end
|
||||
marker:get_luaentity().player_name = name
|
||||
table.insert(markers, marker)
|
||||
end
|
||||
end
|
||||
|
||||
--YZ plane markers
|
||||
for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do
|
||||
local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "techage:region_cube")
|
||||
if marker ~= nil then
|
||||
marker:set_properties({
|
||||
visual_size={x=sizez * 2, y=sizey * 2},
|
||||
--collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez},
|
||||
collisionbox = {0,0,0, 0,0,0},
|
||||
})
|
||||
marker:set_yaw(math.pi / 2)
|
||||
marker:get_luaentity().player_name = name
|
||||
table.insert(markers, marker)
|
||||
end
|
||||
end
|
||||
|
||||
marker_region[name] = markers
|
||||
minetest.after(secs or 20, techage.unmark_region, name)
|
||||
end
|
||||
|
||||
function techage.switch_region(name, pos1, pos2)
|
||||
if marker_region[name] ~= nil then --marker already exists
|
||||
techage.unmark_region(name)
|
||||
else
|
||||
techage.mark_region(name, pos1, pos2)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_entity(":techage:region_cube", {
|
||||
initial_properties = {
|
||||
visual = "upright_sprite",
|
||||
textures = {"techage_cube_mark.png"},
|
||||
use_texture_alpha = true,
|
||||
physical = false,
|
||||
glow = 12,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if marker_region[self.player_name] == nil then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, hitter)
|
||||
techage.unmark_region(self.player_name)
|
||||
end,
|
||||
})
|
@ -1,128 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
mark.lua:
|
||||
|
||||
]]--
|
||||
|
||||
local marker_region = {}
|
||||
|
||||
function techage.unmark_position(name)
|
||||
if marker_region[name] ~= nil then --marker already exists
|
||||
--wip: make the area stay loaded somehow
|
||||
for _, entity in ipairs(marker_region[name]) do
|
||||
entity:remove()
|
||||
end
|
||||
marker_region[name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function techage.mark_position(name, pos, nametag, color, time)
|
||||
local marker = minetest.add_entity(pos, "techage:position_cube")
|
||||
if marker ~= nil then
|
||||
marker:set_nametag_attributes({color = color, text = nametag})
|
||||
marker:get_luaentity().player_name = name
|
||||
if not marker_region[name] then
|
||||
marker_region[name] = {}
|
||||
end
|
||||
marker_region[name][#marker_region[name] + 1] = marker
|
||||
end
|
||||
minetest.after(time or 30, techage.unmark_position, name)
|
||||
end
|
||||
|
||||
function techage.mark_cube(name, pos1, pos2, nametag, color, time)
|
||||
local new_x = pos1.x + ((pos2.x - pos1.x) / 2)
|
||||
local new_y = pos1.y + ((pos2.y - pos1.y) / 2)
|
||||
local new_z = pos1.z + ((pos2.z - pos1.z) / 2)
|
||||
local size_x = math.abs(pos1.x - pos2.x) + 1
|
||||
local size_y = math.abs(pos1.y - pos2.y) + 1
|
||||
local size_z = math.abs(pos1.z - pos2.z) + 1
|
||||
|
||||
local marker = minetest.add_entity(
|
||||
{x = new_x, y = new_y, z = new_z}, "techage:position_cube")
|
||||
if marker ~= nil then
|
||||
marker:set_nametag_attributes({color = color, text = nametag, visual_size = {x = size_x, y = size_y, z = size_z}})
|
||||
marker:get_luaentity().player_name = name
|
||||
marker:set_properties({visual_size = {x = size_x, y = size_y, z = size_z}})
|
||||
if not marker_region[name] then
|
||||
marker_region[name] = {}
|
||||
end
|
||||
marker_region[name][#marker_region[name] + 1] = marker
|
||||
end
|
||||
minetest.after(time or 30, techage.unmark_position, name)
|
||||
end
|
||||
|
||||
minetest.register_entity(":techage:position_cube", {
|
||||
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)
|
||||
if marker_region[self.player_name] == nil then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, hitter)
|
||||
techage.unmark_position(self.player_name)
|
||||
end,
|
||||
})
|
||||
|
||||
function techage.mark_side(name, pos, dir, nametag, color, time)
|
||||
local v = vector.multiply(tubelib2.Dir6dToVector[dir or 0], 0.7)
|
||||
local pos2 = vector.add(pos, v)
|
||||
|
||||
local marker = minetest.add_entity(pos2, "techage:position_side")
|
||||
if marker ~= nil then
|
||||
marker:set_nametag_attributes({color = color, text = nametag})
|
||||
marker:get_luaentity().player_name = name
|
||||
if dir == 2 or dir == 4 then
|
||||
marker:setyaw(math.pi / 2)
|
||||
end
|
||||
|
||||
if not marker_region[name] then
|
||||
marker_region[name] = {}
|
||||
end
|
||||
marker_region[name][#marker_region[name] + 1] = marker
|
||||
end
|
||||
minetest.after(time or 30, techage.unmark_position, name)
|
||||
end
|
||||
|
||||
minetest.register_entity(":techage:position_side", {
|
||||
initial_properties = {
|
||||
visual = "upright_sprite",
|
||||
textures = {"techage_side_mark.png"},
|
||||
physical = false,
|
||||
visual_size = {x = 1.1, y = 1.1, z = 1.1},
|
||||
collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55},
|
||||
glow = 12,
|
||||
},
|
||||
on_step = function(self, dtime)
|
||||
if marker_region[self.player_name] == nil then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end,
|
||||
on_punch = function(self, hitter)
|
||||
techage.unmark_position(self.player_name)
|
||||
end,
|
||||
})
|
@ -1,130 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Block marker lib for door/move/fly controller
|
||||
|
||||
]]--
|
||||
|
||||
local MAX_NUM = 128
|
||||
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 >= MAX_NUM 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_on_leaveplayer(function(ObjectRef, timed_out)
|
||||
if ObjectRef and ObjectRef:is_player() then
|
||||
local name = ObjectRef:get_player_name()
|
||||
marker.unmark_all(name)
|
||||
end
|
||||
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",
|
||||
},
|
||||
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
|
@ -1,561 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
A state model/class for TechAge nodes.
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
--[[
|
||||
|
||||
Node states:
|
||||
|
||||
+-----------------------------------+ +------------+
|
||||
| | | |
|
||||
| V V |
|
||||
| +---------+ |
|
||||
| | | |
|
||||
| +---------| STOPPED | |
|
||||
| | | | |
|
||||
| button | +---------+ |
|
||||
| | ^ |
|
||||
button | V | button |
|
||||
| +---------+ | | button
|
||||
| +--------->| |---------+ |
|
||||
| | power | RUNNING | |
|
||||
| | +------| |---------+ |
|
||||
| | | +---------+ | |
|
||||
| | | ^ | | |
|
||||
| | | | | | |
|
||||
| | V | V V |
|
||||
| +---------+ +----------+ +---------+ |
|
||||
| | | | | | | |
|
||||
+---| NOPOWER | | STANDBY/ | | FAULT |----------+
|
||||
| | | BLOCKED | | |
|
||||
+---------+ +----------+ +---------+
|
||||
|
||||
|
||||
| cycle time operational needs power
|
||||
+---------+------------+-------------+-------------
|
||||
| RUNNING normal yes yes
|
||||
| BLOCKED long yes no
|
||||
| STANDBY long yes no
|
||||
| NOPOWER long no no
|
||||
| FAULT none no no
|
||||
| STOPPED none no no
|
||||
|
||||
Node nvm data:
|
||||
"techage_state" - node state, like "RUNNING"
|
||||
"techage_countdown" - countdown to standby mode
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local N = techage.get_node_lvm
|
||||
|
||||
local MAX_CYCLE_TIME = 20
|
||||
|
||||
--
|
||||
-- TechAge machine states
|
||||
--
|
||||
|
||||
techage.RUNNING = 1 -- in normal operation/turned on
|
||||
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory
|
||||
techage.STANDBY = 3 -- nothing to do (e.g. no input items), or node (world) not loaded
|
||||
techage.NOPOWER = 4 -- only for power consuming nodes, no operation
|
||||
techage.FAULT = 5 -- any fault state (e.g. wrong source items), which can be fixed by the player
|
||||
techage.STOPPED = 6 -- not operational/turned off
|
||||
techage.UNLOADED = 7 -- Map block unloaded
|
||||
techage.INACTIVE = 8 -- Map block loaded but node is not actively working
|
||||
|
||||
techage.StatesImg = {
|
||||
"techage_inv_button_on.png",
|
||||
"techage_inv_button_warning.png",
|
||||
"techage_inv_button_standby.png",
|
||||
"techage_inv_button_nopower.png",
|
||||
"techage_inv_button_error.png",
|
||||
"techage_inv_button_off.png",
|
||||
}
|
||||
|
||||
local function error(pos, msg)
|
||||
minetest.log("error", "[TA states] "..msg.." at "..S(pos).." "..N(pos).name)
|
||||
end
|
||||
|
||||
-- Return state button image for the node inventory
|
||||
function techage.state_button(state)
|
||||
if state and state < 7 and state > 0 then
|
||||
return techage.StatesImg[state]
|
||||
end
|
||||
return "techage_inv_button_off.png"
|
||||
end
|
||||
|
||||
function techage.get_power_image(pos, nvm)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
local s = "3" -- electrical power
|
||||
if string.find(node.name, "techage:ta2") then
|
||||
s = "2" -- axles power
|
||||
end
|
||||
return "techage_inv_powerT"..s..".png"
|
||||
end
|
||||
|
||||
-- State string based on button states
|
||||
techage.StateStrings = {"running", "blocked", "standby", "nopower", "fault", "stopped"}
|
||||
|
||||
--
|
||||
-- Local States
|
||||
--
|
||||
local RUNNING = techage.RUNNING
|
||||
local BLOCKED = techage.BLOCKED
|
||||
local STANDBY = techage.STANDBY
|
||||
local NOPOWER = techage.NOPOWER
|
||||
local FAULT = techage.FAULT
|
||||
local STOPPED = techage.STOPPED
|
||||
|
||||
|
||||
--
|
||||
-- NodeStates Class Functions
|
||||
--
|
||||
techage.NodeStates = {}
|
||||
local NodeStates = techage.NodeStates
|
||||
|
||||
local function can_start(pos, nvm)
|
||||
--if false, node goes in FAULT
|
||||
return true
|
||||
end
|
||||
|
||||
local function has_power(pos, nvm)
|
||||
--if false, node goes in NOPOWER
|
||||
return true
|
||||
end
|
||||
|
||||
local function swap_node(pos, new_name, old_name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == new_name then
|
||||
return
|
||||
end
|
||||
if node.name == old_name then
|
||||
node.name = new_name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
-- true if node_timer should be executed
|
||||
function techage.is_operational(nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
return state < NOPOWER
|
||||
end
|
||||
|
||||
function techage.is_running(nvm)
|
||||
return (nvm.techage_state or STOPPED) == RUNNING
|
||||
end
|
||||
|
||||
-- consumes power
|
||||
function techage.needs_power(nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
return state == RUNNING or state == NOPOWER
|
||||
end
|
||||
|
||||
-- consumes power
|
||||
function techage.needs_power2(state)
|
||||
state = state or STOPPED
|
||||
return state == RUNNING or state == NOPOWER
|
||||
end
|
||||
|
||||
function techage.get_state_string(nvm)
|
||||
return techage.StateStrings[nvm.techage_state or STOPPED]
|
||||
end
|
||||
|
||||
function NodeStates:new(attr)
|
||||
local o = {
|
||||
-- mandatory
|
||||
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,
|
||||
has_power = attr.has_power or has_power,
|
||||
can_start = attr.can_start or can_start,
|
||||
start_node = attr.start_node,
|
||||
stop_node = attr.stop_node,
|
||||
formspec_func = attr.formspec_func,
|
||||
on_state_change = attr.on_state_change,
|
||||
quick_start = attr.quick_start,
|
||||
}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function NodeStates:node_init(pos, nvm, number)
|
||||
nvm.techage_state = STOPPED
|
||||
M(pos):set_string("node_number", number)
|
||||
if self.infotext_name then
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": stopped")
|
||||
end
|
||||
if self.formspec_func then
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
-- to be used to re-start the timer outside of node_timer()
|
||||
local function start_timer_delayed(pos, cycle_time)
|
||||
local t = minetest.get_node_timer(pos)
|
||||
t:stop()
|
||||
if cycle_time > 0.9 then
|
||||
minetest.after(0.1, t.start, t, cycle_time)
|
||||
else
|
||||
error(pos, "invalid cycle_time")
|
||||
end
|
||||
end
|
||||
|
||||
function NodeStates:stop(pos, nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
nvm.techage_state = STOPPED
|
||||
if self.stop_node then
|
||||
self.stop_node(pos, nvm, state)
|
||||
end
|
||||
if self.node_name_passive then
|
||||
swap_node(pos, self.node_name_passive, self.node_name_active)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": stopped")
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = "stopped"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, STOPPED)
|
||||
end
|
||||
if minetest.get_node_timer(pos):is_started() then
|
||||
minetest.get_node_timer(pos):stop()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function NodeStates:start(pos, nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
if state ~= RUNNING and state ~= FAULT then
|
||||
local res = self.can_start(pos, nvm, state)
|
||||
if res ~= true then
|
||||
self:fault(pos, nvm, res)
|
||||
return false
|
||||
end
|
||||
if not self.has_power(pos, nvm, state) then
|
||||
self:nopower(pos, nvm)
|
||||
return false
|
||||
end
|
||||
nvm.techage_state = RUNNING
|
||||
if self.start_node then
|
||||
self.start_node(pos, nvm, state)
|
||||
end
|
||||
nvm.techage_countdown = self.countdown_ticks
|
||||
if self.node_name_active then
|
||||
swap_node(pos, self.node_name_active, self.node_name_passive)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": running")
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = "running"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if minetest.get_node_timer(pos):is_started() then
|
||||
minetest.get_node_timer(pos):stop()
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, RUNNING)
|
||||
end
|
||||
start_timer_delayed(pos, self.cycle_time)
|
||||
|
||||
if self.quick_start and state == STOPPED then
|
||||
self.quick_start(pos, 0)
|
||||
end
|
||||
self:trigger_state(pos, nvm)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function NodeStates:standby(pos, nvm, err_string)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
if state == RUNNING or state == BLOCKED then
|
||||
nvm.techage_state = STANDBY
|
||||
if self.node_name_passive then
|
||||
swap_node(pos, self.node_name_passive, self.node_name_active)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": "..(err_string or "standby"))
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = err_string or "standby"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, STANDBY)
|
||||
end
|
||||
start_timer_delayed(pos, self.cycle_time * self.standby_ticks)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- special case of standby for pushing nodes
|
||||
function NodeStates:blocked(pos, nvm, err_string)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
if state == RUNNING then
|
||||
nvm.techage_state = BLOCKED
|
||||
if self.node_name_passive then
|
||||
swap_node(pos, self.node_name_passive, self.node_name_active)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": "..(err_string or "blocked"))
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = err_string or "blocked"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, BLOCKED)
|
||||
end
|
||||
start_timer_delayed(pos, self.cycle_time * self.standby_ticks)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function NodeStates:nopower(pos, nvm, err_string)
|
||||
local state = nvm.techage_state or RUNNING
|
||||
if state ~= NOPOWER then
|
||||
nvm.techage_state = NOPOWER
|
||||
if self.node_name_passive then
|
||||
swap_node(pos, self.node_name_passive, self.node_name_active)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": "..(err_string or "no power"))
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = err_string or "no power"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, NOPOWER)
|
||||
end
|
||||
start_timer_delayed(pos, self.cycle_time * self.standby_ticks)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function NodeStates:fault(pos, nvm, err_string)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
err_string = err_string or "fault"
|
||||
if state == RUNNING or state == STOPPED then
|
||||
nvm.techage_state = FAULT
|
||||
if self.node_name_passive then
|
||||
swap_node(pos, self.node_name_passive, self.node_name_active)
|
||||
end
|
||||
if self.infotext_name then
|
||||
local number = M(pos):get_string("node_number")
|
||||
M(pos):set_string("infotext", self.infotext_name.." "..number..": "..err_string)
|
||||
end
|
||||
if self.formspec_func then
|
||||
nvm.ta_state_tooltip = err_string or "fault"
|
||||
M(pos):set_string("formspec", self.formspec_func(self, pos, nvm))
|
||||
end
|
||||
if self.on_state_change then
|
||||
self.on_state_change(pos, state, FAULT)
|
||||
end
|
||||
minetest.get_node_timer(pos):stop()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function NodeStates:get_state(nvm)
|
||||
return nvm.techage_state or techage.STOPPED
|
||||
end
|
||||
|
||||
-- keep the timer running?
|
||||
function NodeStates:is_active(nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
return state < FAULT
|
||||
end
|
||||
|
||||
function NodeStates:start_if_standby(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.techage_state == STANDBY then
|
||||
self:start(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- To be called if node is idle.
|
||||
-- If countdown reaches zero, the node is set to STANDBY.
|
||||
function NodeStates:idle(pos, nvm)
|
||||
local countdown = (nvm.techage_countdown or 0) - 1
|
||||
nvm.techage_countdown = countdown
|
||||
if countdown <= 0 then
|
||||
self:standby(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
-- To be called after successful node action to raise the timer
|
||||
-- and keep the node in state RUNNING
|
||||
function NodeStates:keep_running(pos, nvm, val)
|
||||
-- set to RUNNING if not already done
|
||||
if nvm.techage_state ~= RUNNING then
|
||||
self:start(pos, nvm)
|
||||
end
|
||||
nvm.techage_countdown = val or 4
|
||||
nvm.last_active = minetest.get_gametime()
|
||||
end
|
||||
|
||||
function NodeStates:trigger_state(pos, nvm)
|
||||
nvm.last_active = minetest.get_gametime()
|
||||
end
|
||||
|
||||
-- Start/stop node based on button events.
|
||||
-- if function returns false, no button was pressed
|
||||
function NodeStates:state_button_event(pos, nvm, fields)
|
||||
if fields.state_button ~= nil then
|
||||
local state = nvm.techage_state or STOPPED
|
||||
if state == STOPPED or state == STANDBY or state == BLOCKED then
|
||||
if not self:start(pos, nvm) and (state == STANDBY or state == BLOCKED) then
|
||||
self:stop(pos, nvm)
|
||||
end
|
||||
elseif state == RUNNING or state == FAULT or state == NOPOWER then
|
||||
self:stop(pos, nvm)
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function NodeStates:get_state_button_image(nvm)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
return techage.state_button(state)
|
||||
end
|
||||
|
||||
function NodeStates:get_state_tooltip(nvm)
|
||||
local tp = nvm.ta_state_tooltip or ""
|
||||
return tp..";#0C3D32;#FFFFFF"
|
||||
end
|
||||
|
||||
-- command interface
|
||||
function NodeStates:on_receive_message(pos, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "on" then
|
||||
self:start(pos, techage.get_nvm(pos))
|
||||
return true
|
||||
elseif topic == "off" then
|
||||
self:stop(pos, techage.get_nvm(pos))
|
||||
return true
|
||||
elseif topic == "state" then
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "ignore" then -- unloaded node?
|
||||
return "unloaded"
|
||||
elseif nvm.techage_state == RUNNING then
|
||||
local ttl = (nvm.last_active or 0) + MAX_CYCLE_TIME
|
||||
if ttl < minetest.get_gametime() then
|
||||
return "inactive"
|
||||
end
|
||||
end
|
||||
return techage.get_state_string(techage.get_nvm(pos))
|
||||
elseif topic == "fuel" then
|
||||
return techage.fuel.get_fuel_amount(nvm)
|
||||
elseif topic == "load" then
|
||||
return techage.liquid.get_liquid_amount(nvm)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end
|
||||
|
||||
function NodeStates:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
if topic == 1 then
|
||||
if payload[1] == 0 then
|
||||
self:stop(pos, techage.get_nvm(pos))
|
||||
return 0
|
||||
else
|
||||
self:start(pos, techage.get_nvm(pos))
|
||||
return 0
|
||||
end
|
||||
else
|
||||
return 2 -- unknown or invalid topic
|
||||
end
|
||||
end
|
||||
|
||||
function NodeStates:on_beduino_request_data(pos, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == 128 then
|
||||
return 0, techage.get_node_lvm(pos).name
|
||||
elseif topic == 129 then
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "ignore" then -- unloaded node?
|
||||
return 0, {techage.UNLOADED}
|
||||
elseif nvm.techage_state == RUNNING then
|
||||
local ttl = (nvm.last_active or 0) + MAX_CYCLE_TIME
|
||||
if ttl < minetest.get_gametime() then
|
||||
return 0, {techage.INACTIVE}
|
||||
end
|
||||
end
|
||||
return 0, {nvm.techage_state or STOPPED}
|
||||
else
|
||||
return 2, "" -- topic is unknown or invalid
|
||||
end
|
||||
end
|
||||
|
||||
function NodeStates.get_beduino_state(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if node.name == "ignore" then -- unloaded node?
|
||||
return 0, {techage.UNLOADED}
|
||||
elseif nvm.techage_state == RUNNING then
|
||||
local ttl = (nvm.last_active or 0) + MAX_CYCLE_TIME
|
||||
if ttl < minetest.get_gametime() then
|
||||
return 0, {techage.INACTIVE}
|
||||
end
|
||||
end
|
||||
return 0, {nvm.techage_state or STOPPED}
|
||||
end
|
||||
|
||||
-- restart timer
|
||||
function NodeStates:on_node_load(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local state = nvm.techage_state or STOPPED
|
||||
if state == RUNNING then
|
||||
minetest.get_node_timer(pos):start(self.cycle_time)
|
||||
elseif state < FAULT then
|
||||
minetest.get_node_timer(pos):start(self.cycle_time * self.standby_ticks)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:defect_dummy", {
|
||||
description = "Corrupted Node (to be replaced)",
|
||||
tiles = {
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png",
|
||||
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_defect.png",
|
||||
},
|
||||
drop = "",
|
||||
groups = {cracky=2, crumbly=2, choppy=2, not_in_creative_inventory=1},
|
||||
is_ground_content = false,
|
||||
})
|
@ -1,183 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Data storage system for node related volatile and non-volatile data.
|
||||
Non-volatile data is stored from time to time and at shutdown.
|
||||
Volatile data is lost at every shutdown.
|
||||
|
||||
]]--
|
||||
|
||||
local NvmStore = {} -- non-volatile data cache
|
||||
local MemStore = {} -- volatile data cache
|
||||
|
||||
local N = function(pos) print(minetest.pos_to_string(pos), minetest.get_node(pos).name) end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Backend
|
||||
-------------------------------------------------------------------
|
||||
local MP = minetest.get_modpath("techage")
|
||||
local techage_use_sqlite = minetest.settings:get_bool('techage_use_sqlite', false)
|
||||
local backend
|
||||
|
||||
if techage_use_sqlite then
|
||||
backend = dofile(MP .. "/basis/nodedata_sqlite.lua")
|
||||
else
|
||||
backend = dofile(MP .. "/basis/nodedata_meta.lua")
|
||||
end
|
||||
|
||||
-- return keys for mapblock and inner-mapblock addressing based on the node position
|
||||
local function get_keys(pos)
|
||||
local kx1, kx2 = math.floor(pos.x / 16) + 2048, pos.x % 16
|
||||
local ky1, ky2 = math.floor(pos.y / 16) + 2048, pos.y % 16
|
||||
local kz1, kz2 = math.floor(pos.z / 16) + 2048, pos.z % 16
|
||||
return kx1 * 4096 * 4096 + ky1 * 4096 + kz1, kx2 * 16 * 16 + ky2 * 16 + kz2
|
||||
end
|
||||
|
||||
local function pos_from_key(key1, key2)
|
||||
|
||||
local x1 = (math.floor(key1 / (4096 * 4096)) - 2048) * 16
|
||||
local y1 = ((math.floor(key1 / 4096) % 4096) - 2048) * 16
|
||||
local z1 = ((key1 % 4096) - 2048) * 16
|
||||
local x2 = math.floor(key2 / (16 * 16))
|
||||
local y2 = math.floor(key2 / 16) % 16
|
||||
local z2 = key2 % 16
|
||||
|
||||
return {x = x1 + x2, y = y1 + y2, z = z1 + z2}
|
||||
end
|
||||
|
||||
local function debug(key1, item)
|
||||
--local pos1 = pos_from_key(key1, 0)
|
||||
--local pos2 = {x = pos1.x + 15, y = pos1.y + 15, z = pos1.z + 15}
|
||||
--techage.mark_region("mapblock", pos1, pos2, "singleplayer", 5)
|
||||
|
||||
local cnt = 0
|
||||
for key2, tbl in pairs(item) do
|
||||
if key2 ~= "in_use" then
|
||||
cnt = cnt + 1
|
||||
--N(pos_from_key(key1, key2))
|
||||
end
|
||||
end
|
||||
print("mapblock", string.format("%09X", key1), cnt.." nodes")
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Storage scheduler
|
||||
-------------------------------------------------------------------
|
||||
local CYCLE_TIME = 600 -- store data every 10 min
|
||||
local JobQueue = {}
|
||||
local first = 0
|
||||
local last = -1
|
||||
local SystemTime = 0
|
||||
|
||||
local function push(key)
|
||||
last = last + 1
|
||||
JobQueue[last] = {key = key, time = SystemTime + CYCLE_TIME}
|
||||
end
|
||||
|
||||
local function pop()
|
||||
if first > last then return end
|
||||
local item = JobQueue[first]
|
||||
if item.time <= SystemTime then
|
||||
JobQueue[first] = nil -- to allow garbage collection
|
||||
first = first + 1
|
||||
return item.key
|
||||
end
|
||||
end
|
||||
|
||||
-- check every 100 msec if any data has to be stored
|
||||
minetest.register_globalstep(function(dtime)
|
||||
SystemTime = SystemTime + dtime
|
||||
local key = pop()
|
||||
if key and NvmStore[key] then
|
||||
-- minetest.log("warning",
|
||||
-- string.format("[TA Storage] SystemTime = %.3f, #JobQueue = %d, in_use = %s",
|
||||
-- SystemTime, last - first, NvmStore[key].in_use))
|
||||
local t = minetest.get_us_time()
|
||||
if NvmStore[key].in_use then
|
||||
NvmStore[key].in_use = nil
|
||||
backend.store_mapblock_data(key, NvmStore[key])
|
||||
push(key)
|
||||
else
|
||||
NvmStore[key] = nil -- remove unused data from cache
|
||||
end
|
||||
t = minetest.get_us_time() - t
|
||||
if t > 20000 then
|
||||
minetest.log("warning", "[TA Storage] duration = "..(t/1000.0).." ms")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Store/Restore NVM data
|
||||
-------------------------------------------------------------------
|
||||
NvmStore = backend.restore_at_startup()
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
backend.freeze_at_shutdown(NvmStore)
|
||||
end)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------
|
||||
-- Returns volatile node data as table
|
||||
function techage.get_mem(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
if not MemStore[hash] then
|
||||
MemStore[hash] = {}
|
||||
end
|
||||
return MemStore[hash]
|
||||
end
|
||||
|
||||
-- Returns non-volatile node data as table
|
||||
function techage.get_nvm(pos)
|
||||
local key1, key2 = get_keys(pos)
|
||||
|
||||
if not NvmStore[key1] then
|
||||
NvmStore[key1] = backend.get_mapblock_data(key1)
|
||||
push(key1)
|
||||
end
|
||||
|
||||
local block = NvmStore[key1]
|
||||
block.in_use = true
|
||||
if not block[key2] then
|
||||
block[key2] = backend.get_node_data(pos)
|
||||
end
|
||||
return block[key2]
|
||||
end
|
||||
|
||||
-- Returns true/false
|
||||
function techage.has_nvm(pos)
|
||||
local key1, key2 = get_keys(pos)
|
||||
|
||||
if not NvmStore[key1] then
|
||||
NvmStore[key1] = backend.get_mapblock_data(key1)
|
||||
push(key1)
|
||||
end
|
||||
|
||||
return NvmStore[key1][key2] ~= nil
|
||||
end
|
||||
|
||||
function techage.peek_nvm(pos)
|
||||
local key1, key2 = get_keys(pos)
|
||||
local block = NvmStore[key1] or {}
|
||||
return block[key2] or {}
|
||||
end
|
||||
|
||||
-- To be called when a node is removed
|
||||
function techage.del_mem(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
MemStore[hash] = nil
|
||||
|
||||
local key1, key2 = get_keys(pos)
|
||||
NvmStore[key1] = NvmStore[key1] or backend.get_mapblock_data(key1)
|
||||
NvmStore[key1][key2] = nil
|
||||
backend.store_mapblock_data(key1, NvmStore[key1])
|
||||
end
|
@ -1,103 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Storage backend for node related data as node metadata
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
|
||||
local storage = techage.storage
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Marshaling
|
||||
-------------------------------------------------------------------
|
||||
local use_marshal = minetest.settings:get_bool('techage_use_marshal', false)
|
||||
local MAR_MAGIC = 0x8e
|
||||
|
||||
-- default functions
|
||||
local serialize = minetest.serialize
|
||||
local deserialize = minetest.deserialize
|
||||
|
||||
if use_marshal then
|
||||
if not techage.IE then
|
||||
error("Please add 'secure.trusted_mods = techage' to minetest.conf!")
|
||||
end
|
||||
local marshal = techage.IE.require("marshal")
|
||||
if not marshal then
|
||||
error("Please install marshal via 'luarocks install lua-marshal'")
|
||||
end
|
||||
|
||||
serialize = marshal.encode
|
||||
|
||||
deserialize = function(s)
|
||||
if s ~= "" then
|
||||
if s:byte(1) == MAR_MAGIC then
|
||||
return marshal.decode(s)
|
||||
else
|
||||
return minetest.deserialize(s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------
|
||||
local api = {}
|
||||
|
||||
function api.get_mapblock_data(key)
|
||||
return {}
|
||||
end
|
||||
|
||||
function api.store_mapblock_data(key, mapblock_data)
|
||||
for key, item in pairs(mapblock_data) do
|
||||
if key ~= "in_use" then
|
||||
local pos = item and item._POS_
|
||||
if pos then
|
||||
item._POS_ = nil
|
||||
local data = serialize(item)
|
||||
item._POS_ = pos
|
||||
local meta = M(pos)
|
||||
meta:set_string("ta_data", data)
|
||||
meta:mark_as_private("ta_data")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function api.get_node_data(pos)
|
||||
local tbl = {}
|
||||
local s = M(pos):get_string("ta_data")
|
||||
|
||||
if s ~= "" then
|
||||
tbl = deserialize(s) or {}
|
||||
end
|
||||
tbl._POS_ = table.copy(pos)
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
-- Meta data can't be written reliable at shutdown,
|
||||
-- so we have to store/restore the data differently
|
||||
function api.freeze_at_shutdown(data)
|
||||
storage:set_string("shutdown_nodedata", serialize(data))
|
||||
end
|
||||
|
||||
function api.restore_at_startup()
|
||||
local s = storage:get_string("shutdown_nodedata")
|
||||
if s ~= "" then
|
||||
return deserialize(s) or {}
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
return api
|
@ -1,123 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Storage backend for node related data via sqlite database
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Database
|
||||
-------------------------------------------------------------------
|
||||
local MN = minetest.get_current_modname()
|
||||
local WP = minetest.get_worldpath()
|
||||
local use_marshal = minetest.settings:get_bool('techage_use_marshal', false)
|
||||
local MAR_MAGIC = 0x8e
|
||||
|
||||
if not techage.IE then
|
||||
error("Please add 'secure.trusted_mods = techage' to minetest.conf!")
|
||||
end
|
||||
|
||||
local sqlite3 = techage.IE.require("lsqlite3")
|
||||
local marshal = techage.IE.require("marshal")
|
||||
|
||||
if not sqlite3 then
|
||||
error("Please install sqlite3 via 'luarocks install lsqlite3'")
|
||||
end
|
||||
if not marshal then
|
||||
error("Please install marshal via 'luarocks install lua-marshal'")
|
||||
end
|
||||
|
||||
local db = sqlite3.open(WP.."/techage_nodedata.sqlite")
|
||||
local ROW = sqlite3.ROW
|
||||
|
||||
-- Prevent use of this db instance.
|
||||
if sqlite3 then sqlite3 = nil end
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE mapblocks(id INTEGER PRIMARY KEY, key INTEGER, data BLOB);
|
||||
CREATE UNIQUE INDEX idx ON mapblocks(key);
|
||||
]]
|
||||
|
||||
local set = db:prepare("INSERT or REPLACE INTO mapblocks VALUES(NULL, ?, ?);")
|
||||
local get = db:prepare("SELECT * FROM mapblocks WHERE key=?;")
|
||||
|
||||
local function set_block(key, data)
|
||||
set:reset()
|
||||
set:bind(1, key)
|
||||
set:bind_blob(2, data)
|
||||
set:step()
|
||||
end
|
||||
|
||||
local function get_block(key)
|
||||
get:reset()
|
||||
get:bind(1, key)
|
||||
if get:step() == ROW then
|
||||
return get:get_value(2)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------
|
||||
local api = {}
|
||||
|
||||
function api.store_mapblock_data(key, mapblock_data)
|
||||
if use_marshal and mapblock_data then
|
||||
local data = marshal.encode(mapblock_data)
|
||||
if data then
|
||||
set_block(key, data)
|
||||
end
|
||||
else
|
||||
set_block(key, minetest.serialize(mapblock_data))
|
||||
end
|
||||
end
|
||||
|
||||
function api.get_mapblock_data(key)
|
||||
local s = get_block(key)
|
||||
if s then
|
||||
if s:byte(1) == MAR_MAGIC then
|
||||
return marshal.decode(s)
|
||||
else
|
||||
return minetest.deserialize(s)
|
||||
end
|
||||
end
|
||||
api.store_mapblock_data(key, {})
|
||||
return {}
|
||||
end
|
||||
|
||||
function api.get_node_data(pos)
|
||||
-- legacy data available?
|
||||
local s = M(pos):get_string("ta_data")
|
||||
if s ~= "" then
|
||||
M(pos):set_string("ta_data", "")
|
||||
if s:byte(1) == MAR_MAGIC then
|
||||
return marshal.decode(s)
|
||||
else
|
||||
return minetest.deserialize(s)
|
||||
end
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
function api.freeze_at_shutdown(data)
|
||||
for key, item in pairs(data) do
|
||||
api.store_mapblock_data(key, item)
|
||||
end
|
||||
end
|
||||
|
||||
function api.restore_at_startup()
|
||||
-- nothing to restore
|
||||
return {}
|
||||
end
|
||||
|
||||
return api
|
@ -1,142 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Storage backend for node number mapping via sqlite database
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
|
||||
local storage = techage.storage
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Database
|
||||
-------------------------------------------------------------------
|
||||
local MN = minetest.get_current_modname()
|
||||
local WP = minetest.get_worldpath()
|
||||
local MAR_MAGIC = 0x8e
|
||||
|
||||
if not techage.IE then
|
||||
error("Please add 'secure.trusted_mods = techage' to minetest.conf!")
|
||||
end
|
||||
|
||||
local sqlite3 = techage.IE.require("lsqlite3")
|
||||
local marshal = techage.IE.require("marshal")
|
||||
|
||||
if not sqlite3 then
|
||||
error("Please install sqlite3 via 'luarocks install lsqlite3'")
|
||||
end
|
||||
if not marshal then
|
||||
error("Please install marshal via 'luarocks install lua-marshal'")
|
||||
end
|
||||
|
||||
local db = sqlite3.open(WP.."/techage_numbers.sqlite")
|
||||
local ROW = sqlite3.ROW
|
||||
|
||||
-- Prevent use of this db instance.
|
||||
if sqlite3 then sqlite3 = nil end
|
||||
|
||||
db:exec[[
|
||||
CREATE TABLE numbers(id INTEGER PRIMARY KEY, number INTEGER, x INTEGER, y INTEGER, z INTEGER);
|
||||
CREATE UNIQUE INDEX idx ON numbers(number);
|
||||
]]
|
||||
|
||||
local set = db:prepare("INSERT or REPLACE INTO numbers VALUES(NULL, ?, ?, ?, ?);")
|
||||
local get = db:prepare("SELECT * FROM numbers WHERE number=?;")
|
||||
|
||||
local function set_block(number, pos)
|
||||
set:reset()
|
||||
set:bind(1, number)
|
||||
set:bind(2, pos.x)
|
||||
set:bind(3, pos.y)
|
||||
set:bind(4, pos.z)
|
||||
set:step()
|
||||
return true
|
||||
end
|
||||
|
||||
local function get_block(number)
|
||||
get:reset()
|
||||
get:bind(1, number)
|
||||
if get:step() == ROW then
|
||||
return {x = get:get_value(2), y = get:get_value(3), z = get:get_value(4)}
|
||||
end
|
||||
end
|
||||
|
||||
local function del_block(number)
|
||||
db:exec("DELETE FROM numbers WHERE number="..number..";")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Migration from mod storage
|
||||
-------------------------------------------------------------------
|
||||
local Version = storage:get_int("Version") or 0
|
||||
local NextNumber = 0
|
||||
|
||||
if Version == 0 then
|
||||
Version = 4
|
||||
end
|
||||
if Version == 3 then
|
||||
Version = 4
|
||||
NextNumber = storage:get_int("NextNumber")
|
||||
for i = 1, NextNumber do
|
||||
local number = tostring(i)
|
||||
if storage:contains(number) then
|
||||
local pos = minetest.string_to_pos(storage:get_string(number))
|
||||
set_block(number, pos)
|
||||
storage:set_string(number, "")
|
||||
end
|
||||
end
|
||||
elseif Version == 4 then
|
||||
NextNumber = storage:get_int("NextNumber")
|
||||
else
|
||||
error("[] Invalid version number for 'number to pos mapping' table!")
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------
|
||||
local api = {}
|
||||
|
||||
function api.get_nodepos(number)
|
||||
return get_block(number)
|
||||
end
|
||||
|
||||
function api.set_nodepos(number, pos)
|
||||
set_block(number, pos)
|
||||
end
|
||||
|
||||
function api.add_nodepos(pos)
|
||||
local num = tostring(NextNumber)
|
||||
NextNumber = NextNumber + 1
|
||||
storage:set_int("NextNumber", NextNumber)
|
||||
set_block(num, pos)
|
||||
return num
|
||||
end
|
||||
|
||||
function api.del_nodepos(number)
|
||||
del_block(number)
|
||||
end
|
||||
|
||||
-- delete invalid entries
|
||||
function api.delete_invalid_entries(node_def)
|
||||
minetest.log("info", "[TechAge] Data maintenance started")
|
||||
for id, num, x, y, z in db:urows('SELECT * FROM numbers') do
|
||||
local pos = {x = x, y = y, z = z}
|
||||
local name = techage.get_node_lvm(pos).name
|
||||
if not node_def[name] then
|
||||
del_block(num)
|
||||
end
|
||||
end
|
||||
minetest.log("info", "[TechAge] Data maintenance finished")
|
||||
end
|
||||
|
||||
return api
|
@ -1,98 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Storage backend for node number mapping via mod storage
|
||||
|
||||
]]--
|
||||
|
||||
local backend = {}
|
||||
local storage = techage.storage
|
||||
|
||||
-- legacy method
|
||||
local function deserialize(s)
|
||||
local tbl = {}
|
||||
for line in s:gmatch("[^;]+") do
|
||||
local num, spos = unpack(string.split(line, "="))
|
||||
tbl[num] = minetest.string_to_pos(spos)
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
|
||||
local Version = minetest.deserialize(storage:get_string("Version")) or 3
|
||||
local NextNumber = 0
|
||||
|
||||
if Version == 1 then
|
||||
Version = 3
|
||||
local tbl = minetest.deserialize(storage:get_string("Number2Pos")) or {}
|
||||
NextNumber = minetest.deserialize(storage:get_string("NextNumber")) or 1
|
||||
for num, pos in pairs(tbl) do
|
||||
storage:set_string(num, minetest.pos_to_string(pos))
|
||||
end
|
||||
storage:set_string("Number2Pos", "")
|
||||
elseif Version == 2 then
|
||||
Version = 3
|
||||
NextNumber = minetest.deserialize(storage:get_string("NextNumber")) or 1
|
||||
local tbl = deserialize(storage:get_string("Number2Pos"))
|
||||
for num, pos in pairs(tbl) do
|
||||
storage:set_string(num, minetest.pos_to_string(pos))
|
||||
end
|
||||
storage:set_string("Number2Pos", "")
|
||||
else
|
||||
Version = 3
|
||||
NextNumber = storage:get_int("NextNumber")
|
||||
end
|
||||
|
||||
storage:set_int("NextNumber", NextNumber)
|
||||
storage:set_int("Version", Version)
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- API functions
|
||||
-------------------------------------------------------------------
|
||||
function backend.get_nodepos(number)
|
||||
return minetest.string_to_pos(storage:get_string(number))
|
||||
end
|
||||
|
||||
function backend.set_nodepos(number, pos)
|
||||
storage:set_string(number, minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
function backend.add_nodepos(pos)
|
||||
local num = tostring(NextNumber)
|
||||
NextNumber = NextNumber + 1
|
||||
storage:set_int("NextNumber", NextNumber)
|
||||
storage:set_string(num, minetest.pos_to_string(pos))
|
||||
return num
|
||||
end
|
||||
|
||||
function backend.del_nodepos(number)
|
||||
storage:set_string(number, "")
|
||||
end
|
||||
|
||||
-- delete invalid entries
|
||||
function backend.delete_invalid_entries(node_def)
|
||||
minetest.log("info", "[TechAge] Data maintenance started")
|
||||
for i = 1, NextNumber do
|
||||
local number = tostring(i)
|
||||
if storage:contains(number) then
|
||||
local pos = backend.get_nodepos(number)
|
||||
local name = techage.get_node_lvm(pos).name
|
||||
if not node_def[name] then
|
||||
backend.del_nodepos(number)
|
||||
else
|
||||
minetest.get_meta(pos):set_string("node_number", number)
|
||||
end
|
||||
end
|
||||
end
|
||||
minetest.log("info", "[TechAge] Data maintenance finished")
|
||||
end
|
||||
|
||||
return backend
|
@ -1,103 +0,0 @@
|
||||
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
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2024 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Packing functions
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local M = minetest.get_meta
|
||||
|
||||
-- string/usercode conversion
|
||||
local function usercode_to_string(tbl)
|
||||
if tbl and tbl.inventory then
|
||||
for list_name,list in pairs(tbl.inventory) do
|
||||
for i,item in ipairs(list) do
|
||||
tbl.inventory[list_name][i] = item:to_string()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function string_to_usercode(tbl)
|
||||
if tbl and tbl.inventory then
|
||||
for list_name,list in pairs(tbl.inventory) do
|
||||
for i,item in ipairs(list) do
|
||||
tbl.inventory[list_name][i] = ItemStack(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- pack/unpack node nvm data
|
||||
local function pack_nvm(pos)
|
||||
if techage.has_nvm(pos) then
|
||||
local s = minetest.serialize(techage.get_nvm(pos))
|
||||
techage.del_mem(pos)
|
||||
return s
|
||||
end
|
||||
end
|
||||
|
||||
local function unpack_nvm(pos, s)
|
||||
if s and s ~= "" then
|
||||
local tbl = minetest.deserialize(s)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
for k,v in pairs(tbl) do
|
||||
nvm.k = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- pack/unpack node metedata
|
||||
local function pack_meta(pos)
|
||||
local tbl = M(pos):to_table() or {}
|
||||
usercode_to_string(tbl)
|
||||
return minetest.serialize(tbl)
|
||||
end
|
||||
|
||||
local function unpack_meta(pos, s)
|
||||
if s and s ~= "" then
|
||||
local tbl = minetest.deserialize(s) or {}
|
||||
string_to_usercode(tbl)
|
||||
M(pos):from_table(tbl)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- preserve/restore API functions
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function techage.preserve_nodedata(pos)
|
||||
local smeta = pack_meta(pos)
|
||||
local snvm = pack_nvm(pos)
|
||||
return minetest.serialize({smeta = smeta, snvm = snvm})
|
||||
end
|
||||
|
||||
function techage.restore_nodedata(pos, s)
|
||||
local tbl = minetest.deserialize(s) or {}
|
||||
unpack_nvm(pos, tbl.snvm)
|
||||
unpack_meta(pos, tbl.smeta)
|
||||
end
|
@ -1,292 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Recipe lib for formspecs
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local M = minetest.get_meta
|
||||
|
||||
local Recipes = {} -- {rtype = {ouput = {....},...}}
|
||||
local NormalizedRecipes = {} -- {output = "", items = {...}}
|
||||
|
||||
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},
|
||||
input = {
|
||||
{name = "", num =0},
|
||||
{name = "", num =0},
|
||||
{name = "", num =0},
|
||||
{name = "", num =0},
|
||||
},
|
||||
}
|
||||
|
||||
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)
|
||||
local tbl = {}
|
||||
for idx, item in ipairs(recipe.input) do
|
||||
local x = ((idx-1) % 2)
|
||||
local y = math.floor((idx-1) / 2)
|
||||
tbl[idx] = techage.item_image(x, y, item.name.." "..item.num)
|
||||
end
|
||||
return table.concat(tbl, "")
|
||||
end
|
||||
|
||||
function techage.recipes.get(nvm, rtype, owner)
|
||||
local recipes = Recipes[rtype] or {}
|
||||
if owner then
|
||||
recipes = filter_recipes_based_on_points(recipes, owner)
|
||||
end
|
||||
return recipes[nvm.recipe_idx or 1] or recipes[1]
|
||||
end
|
||||
|
||||
-- Add 4 input/output/waste recipe
|
||||
-- {
|
||||
-- output = "<item-name> <units>", -- units = 1..n
|
||||
-- waste = "<item-name> <units>", -- units = 1..n
|
||||
-- input = { -- up to 4 items
|
||||
-- "<item-name> <units>",
|
||||
-- "<item-name> <units>",
|
||||
-- },
|
||||
-- }
|
||||
function techage.recipes.add(rtype, recipe)
|
||||
if not Recipes[rtype] then
|
||||
Recipes[rtype] = {}
|
||||
end
|
||||
|
||||
local name, num, output
|
||||
local item = {input = {}}
|
||||
for idx = 1,4 do
|
||||
local inp = recipe.input[idx] or ""
|
||||
name, num = unpack(string.split(inp, " "))
|
||||
item.input[idx] = {name = name or "", num = tonumber(num) or 0}
|
||||
end
|
||||
if recipe.waste then
|
||||
name, num = unpack(string.split(recipe.waste, " "))
|
||||
else
|
||||
name, num = "", "0"
|
||||
end
|
||||
item.waste = {name = name or "", num = tonumber(num) or 0}
|
||||
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
|
||||
|
||||
techage.recipes.register_craft({
|
||||
output = recipe.output,
|
||||
items = recipe.input,
|
||||
type = rtype,
|
||||
})
|
||||
NormalizedRecipes[output] = {
|
||||
output = recipe.output,
|
||||
items = recipe.input,
|
||||
}
|
||||
end
|
||||
|
||||
function techage.recipes.formspec(x, y, rtype, nvm, 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
|
||||
local output = recipe.output.name.." "..recipe.output.num
|
||||
local waste = recipe.waste.name.." "..recipe.waste.num
|
||||
local catalyst = recipe.catalyst and techage.item_image_small(2.05, 0, recipe.catalyst, S("Catalyst")) or ""
|
||||
return "container["..x..","..y.."]"..
|
||||
"background[0,0;4,3;techage_form_grey.png]"..
|
||||
input_string(recipe)..
|
||||
"image[2,0.7;1,1;techage_form_arrow.png]"..
|
||||
catalyst..
|
||||
techage.item_image(2.95, 0, output)..
|
||||
techage.item_image(2.95, 1, waste)..
|
||||
"button[0,2;1,1;priv;<<]"..
|
||||
"button[1,2;1,1;next;>>]"..
|
||||
"label[1.9,2.2;"..S("Recipe")..": "..idx.."/"..#recipes.."]"..
|
||||
"container_end[]"
|
||||
end
|
||||
|
||||
function techage.recipes.on_receive_fields(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 not nvm.running then
|
||||
if fields.next == ">>" then
|
||||
nvm.recipe_idx = nvm.recipe_idx + 1
|
||||
return true
|
||||
elseif fields.priv == "<<" then
|
||||
nvm.recipe_idx = nvm.recipe_idx - 1
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function techage.recipes.get_recipe(name)
|
||||
return NormalizedRecipes[name]
|
||||
end
|
||||
|
||||
function techage.recipes.set_recipe(pos, rtype, idx)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not nvm.running then
|
||||
local recipes = Recipes[rtype] or {}
|
||||
idx = tonumber(idx) or 1
|
||||
nvm.recipe_idx = range(idx, 1, #recipes)
|
||||
end
|
||||
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
|
@ -1,74 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 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 rmt_pos and 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)
|
||||
if rmt_pos then
|
||||
copy_inventory_list(rmt_pos, pos, listname)
|
||||
return true
|
||||
end
|
||||
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)
|
||||
if rmt_pos then
|
||||
copy_inventory_list(pos, rmt_pos, listname)
|
||||
return true
|
||||
end
|
||||
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)
|
||||
if rmt_pos then
|
||||
copy_inventory_list(rmt_pos, pos, listname)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
minetest.get_node_timer(pos):start(2)
|
||||
end
|
||||
end
|
||||
end
|
@ -1,116 +0,0 @@
|
||||
--[[
|
||||
|
||||
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 is_paired = techage.hyperloop.is_paired
|
||||
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) and is_paired(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)
|
||||
if is_paired(pos) then
|
||||
pos = remote_pos(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return liquid.srv_peek(nvm)
|
||||
end
|
||||
end
|
||||
|
||||
function techage.shared_tank.take_liquid(pos, indir, name, amount)
|
||||
if is_paired(pos) then
|
||||
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
|
||||
return 0, name
|
||||
end
|
||||
|
||||
function techage.shared_tank.put_liquid(pos, indir, name, amount)
|
||||
if is_paired(pos) then
|
||||
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
|
||||
end
|
||||
return amount
|
||||
end
|
||||
|
||||
function techage.shared_tank.untake_liquid(pos, indir, name, amount)
|
||||
if is_paired(pos) then
|
||||
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
|
||||
return amount
|
||||
end
|
||||
|
||||
techage.shared_tank.formspec = formspec
|
@ -1,318 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
A formspec control to generate formspec strings for machine settings and monitoring
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
|
||||
techage.menu = {}
|
||||
|
||||
local function index(list, x)
|
||||
for idx, v in ipairs(list or {}) do
|
||||
if tostring(v) == x then return idx end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function allow_put(inv, listname, index, stack, player)
|
||||
local list = inv:get_list(listname)
|
||||
stack:set_count(1)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_take(inv, listname, index, stack, player)
|
||||
local list = inv:get_list(listname)
|
||||
stack:set_count(0)
|
||||
inv:set_stack(listname, index, stack)
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-- generate the formspec string to be placed into a container frame
|
||||
local function generate_formspec_substring(pos, meta, form_def, player_name)
|
||||
local tbl = {}
|
||||
local player_inv_needed = false
|
||||
if meta and form_def then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
|
||||
for i,elem in ipairs(form_def) do
|
||||
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 == "label" then
|
||||
-- none
|
||||
elseif elem.type == "number" then
|
||||
local val = elem.default
|
||||
if meta:contains(elem.name) then
|
||||
val = meta:get_int(elem.name)
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
|
||||
else
|
||||
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
|
||||
end
|
||||
elseif elem.type == "numbers" then
|
||||
local val = elem.default
|
||||
if meta:contains(elem.name) then
|
||||
val = meta:get_string(elem.name)
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
|
||||
else
|
||||
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
|
||||
end
|
||||
elseif elem.type == "float" then
|
||||
local val = elem.default
|
||||
if meta:contains(elem.name) then
|
||||
val = tonumber(meta:get_string(elem.name)) or 0
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
|
||||
else
|
||||
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. val .. "]"
|
||||
end
|
||||
elseif elem.type == "ascii" then
|
||||
local val = elem.default
|
||||
if meta:contains(elem.name) then
|
||||
val = meta:get_string(elem.name)
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. minetest.formspec_escape(val) .. "]"
|
||||
else
|
||||
tbl[#tbl+1] = "field[5," .. (offs+0.2) .. ";5.3,1;" .. elem.name .. ";;" .. minetest.formspec_escape(val) .. "]"
|
||||
end
|
||||
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 meta:get_string(elem.name) or ""
|
||||
if tonumber(val) then
|
||||
val = techage.round(val)
|
||||
end
|
||||
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. val .. "]"
|
||||
elseif elem.type == "dropdown" then
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
local val = elem.default or ""
|
||||
if meta:contains(elem.name) then
|
||||
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
|
||||
val = meta:get_string(elem.name) or ""
|
||||
end
|
||||
local idx
|
||||
if elem.values then
|
||||
idx = index(elem.values, val) or 1
|
||||
else
|
||||
local l = elem.choices:split(",")
|
||||
idx = index(l, val) or 1
|
||||
end
|
||||
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. elem.choices .. ";" .. idx .. "]"
|
||||
end
|
||||
elseif elem.type == "items" then -- inventory
|
||||
if elem.size then
|
||||
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.size .. ",1;]"
|
||||
else
|
||||
tbl[#tbl+1] = "list[detached:" .. minetest.formspec_escape(player_name) .. "_techage_wrench_menu;cfg;4.75," .. offs .. ";" .. elem.width .. "," .. elem.height .. ";]"
|
||||
end
|
||||
player_inv_needed = true
|
||||
end
|
||||
end
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
local offs = #form_def * 0.9 - 0.2
|
||||
tbl[#tbl+1] = "label[0," .. offs .. ";" .. S("Note: You can't change any values while the block is running!") .. "]"
|
||||
end
|
||||
end
|
||||
|
||||
return player_inv_needed, table.concat(tbl, "")
|
||||
end
|
||||
|
||||
local function value_check(elem, value, player_name)
|
||||
if elem.check then
|
||||
return elem.check(value, player_name)
|
||||
end
|
||||
return value ~= nil
|
||||
end
|
||||
|
||||
local function evaluate_data(pos, meta, form_def, fields, player_name)
|
||||
local res = true
|
||||
|
||||
if meta and form_def then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.running or techage.is_running(nvm) then
|
||||
return res
|
||||
end
|
||||
for idx,elem in ipairs(form_def) do
|
||||
if elem.type == "number" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name] == "" then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name]:find("^[%d ]+$") then
|
||||
local val = tonumber(fields[elem.name])
|
||||
if value_check(elem, val, player_name) then
|
||||
meta:set_int(elem.name, val)
|
||||
--print("set_int", elem.name, val)
|
||||
else
|
||||
res = false
|
||||
end
|
||||
else
|
||||
res = false
|
||||
end
|
||||
end
|
||||
elseif elem.type == "numbers" then
|
||||
if fields[elem.name] then
|
||||
if fields[elem.name] == "" then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name]:find("^[%d ]+$") and
|
||||
value_check(elem, fields[elem.name], player_name) then
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
else
|
||||
res = false
|
||||
end
|
||||
end
|
||||
elseif elem.type == "float" then
|
||||
if fields[elem.name] == ""then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name] then
|
||||
local val = tonumber(fields[elem.name])
|
||||
if val and value_check(elem, val, player_name) then
|
||||
meta:set_string(elem.name, val)
|
||||
else
|
||||
res = false
|
||||
end
|
||||
end
|
||||
elseif elem.type == "ascii" then
|
||||
if fields[elem.name] == ""then
|
||||
meta:set_string(elem.name, "")
|
||||
elseif fields[elem.name] then
|
||||
if value_check(elem, fields[elem.name], player_name) then
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
else
|
||||
res = false
|
||||
end
|
||||
end
|
||||
elseif elem.type == "dropdown" then
|
||||
if fields[elem.name] ~= nil then
|
||||
if elem.values then
|
||||
local l = elem.choices:split(",")
|
||||
local idx = index(l, fields[elem.name]) or 1
|
||||
local text = elem.values[idx]
|
||||
meta:set_string(elem.name, text)
|
||||
else
|
||||
meta:set_string(elem.name, fields[elem.name])
|
||||
end
|
||||
end
|
||||
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})
|
||||
if dinv and ninv then
|
||||
for i = 1, ninv:get_size("cfg") do
|
||||
ninv:set_stack("cfg", i, dinv:get_stack("cfg", i))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function techage.menu.generate_formspec(pos, ndef, form_def, player_name)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local number = techage.get_node_number(pos) or "-"
|
||||
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,
|
||||
allow_take = allow_take})
|
||||
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
|
||||
local ninv = minetest.get_inventory({type = "node", pos = pos})
|
||||
if dinv and ninv then
|
||||
dinv:set_size('cfg', ninv:get_size("cfg"))
|
||||
for i = 1, ninv:get_size("cfg") do
|
||||
dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
|
||||
end
|
||||
end
|
||||
end
|
||||
if meta and number and ndef and form_def then
|
||||
local title = ndef.description .. " (" .. number .. ")"
|
||||
local player_inv_needed, text = generate_formspec_substring(pos, meta, form_def, player_name)
|
||||
local buttons
|
||||
|
||||
if player_inv_needed then
|
||||
buttons = "button[0.5,6.2;3,1;refresh;" .. S("Refresh") .. "]" ..
|
||||
"button_exit[3.5,6.2;3,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[6.5,6.2;3,1;save;" .. S("Save") .. "]" ..
|
||||
"list[current_player;main;1,7.2;8,2;]"
|
||||
else
|
||||
buttons = "button[0.5,8.4;3,1;refresh;" .. S("Refresh") .. "]" ..
|
||||
"button_exit[3.5,8.4;3,1;cancel;" .. S("Cancel") .. "]" ..
|
||||
"button[6.5,8.4;3,1;save;" .. S("Save") .. "]"
|
||||
end
|
||||
|
||||
if #form_def > 8 then
|
||||
local size = (#form_def * 10) - 60
|
||||
return "size[10,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
|
||||
"scrollbaroptions[max=" .. size .. "]" ..
|
||||
"scrollbar[9.4,0.6;0.4,7.7;vertical;wrenchmenu;]" ..
|
||||
"scroll_container[0,1;12,9;wrenchmenu;vertical;]" ..
|
||||
text ..
|
||||
"scroll_container_end[]" ..
|
||||
buttons
|
||||
else
|
||||
return "size[10,9]" ..
|
||||
default.gui_bg ..
|
||||
default.gui_bg_img ..
|
||||
default.gui_slots ..
|
||||
"box[0,-0.1;9.8,0.5;#c6e8ff]" ..
|
||||
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
|
||||
"label[9.5,-0.1;" .. minetest.colorize( "#000000", star) .. "]" ..
|
||||
"container[0,1]" ..
|
||||
text ..
|
||||
"container_end[]" ..
|
||||
buttons
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
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 or fields.key_enter_field
|
||||
end
|
||||
|
||||
function techage.dropdown_index(sChoices, selected_value)
|
||||
local l = sChoices:split(",")
|
||||
return index(l, selected_value) or 1
|
||||
end
|
@ -1,167 +0,0 @@
|
||||
--[[
|
||||
|
||||
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
|
@ -1,57 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tube wall entry
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
|
||||
local Tube = techage.Tube
|
||||
|
||||
minetest.register_node("techage:tube_wall_entry", {
|
||||
description = S("Tube Wall Entry"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png^techage_tube_hole.png",
|
||||
"basic_materials_concrete_block.png^techage_tube_hole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
if not Tube: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)
|
||||
Tube:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir", -- important!
|
||||
on_rotate = screwdriver.disallow, -- important!
|
||||
groups = {crumbly = 2, cracky = 2, snappy = 2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:tube_wall_entry",
|
||||
recipe = {
|
||||
{"", "techage:tubeS", ""},
|
||||
{"", "basic_materials:concrete_block", ""},
|
||||
{"", "",""},
|
||||
},
|
||||
})
|
@ -1,148 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tubes based on tubelib2
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
|
||||
|
||||
-- used for registered nodes
|
||||
techage.KnownNodes = {
|
||||
["techage:tubeS"] = true,
|
||||
["techage:tubeA"] = true,
|
||||
["techage:ta4_tubeS"] = true,
|
||||
["techage:ta4_tubeA"] = true,
|
||||
}
|
||||
|
||||
|
||||
local Tube = tubelib2.Tube:new({
|
||||
-- North, East, South, West, Down, Up
|
||||
dirs_to_check = {1,2,3,4,5,6},
|
||||
max_tube_length = 200,
|
||||
show_infotext = false,
|
||||
primary_node_names = {
|
||||
"techage:tubeS", "techage:tubeA",
|
||||
"techage:ta4_tubeS", "techage:ta4_tubeA",
|
||||
"techage:tube_wall_entry",
|
||||
},
|
||||
after_place_tube = function(pos, param2, tube_type, num_tubes, tbl)
|
||||
local name = minetest.get_node(pos).name
|
||||
if name == "techage:tubeS" or name == "techage:tubeA" then
|
||||
minetest.swap_node(pos, {name = "techage:tube"..tube_type, param2 = param2})
|
||||
elseif name == "techage:tube_wall_entry" then
|
||||
minetest.swap_node(pos, {name = "techage:tube_wall_entry", param2 = param2})
|
||||
else
|
||||
minetest.swap_node(pos, {name = "techage:ta4_tube"..tube_type, param2 = param2})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
techage.Tube = Tube
|
||||
|
||||
minetest.register_node("techage:tubeS", {
|
||||
description = S("TechAge Tube"),
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"techage_tube_tube.png^[transformR90",
|
||||
"techage_tube_tube.png^[transformR90",
|
||||
"techage_tube_tube.png",
|
||||
"techage_tube_tube.png",
|
||||
"techage_tube_hole.png",
|
||||
"techage_tube_hole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
if not Tube: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)
|
||||
Tube:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, -2/8, -4/8, 2/8, 2/8, 4/8},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
|
||||
},
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy=2, cracky=3},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:tubeA", {
|
||||
description = S("TechAge Tube"),
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"techage_tube_knee2.png",
|
||||
"techage_tube_hole2.png^[transformR180",
|
||||
"techage_tube_knee.png^[transformR270",
|
||||
"techage_tube_knee.png",
|
||||
"techage_tube_knee2.png",
|
||||
"techage_tube_hole2.png",
|
||||
},
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, -4/8, -2/8, 2/8, 2/8, 2/8},
|
||||
{-2/8, -2/8, -4/8, 2/8, 2/8, -2/8},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
|
||||
},
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy=2, cracky=3, not_in_creative_inventory=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "techage:tubeS",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:tubeS 4",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "", "group:wood"},
|
||||
{"", "group:wood", ""},
|
||||
{"group:wood", "", "default:tin_ingot"},
|
||||
},
|
||||
})
|
@ -1,120 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Tubes in TA4 design based on tubelib2
|
||||
|
||||
]]--
|
||||
|
||||
local Tube = techage.Tube
|
||||
local S = techage.S
|
||||
|
||||
minetest.register_node("techage:ta4_tubeS", {
|
||||
description = S("TA4 Tube"),
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"techage_tubeta4_tube.png^[transformR90",
|
||||
"techage_tubeta4_tube.png^[transformR90",
|
||||
"techage_tubeta4_tube.png",
|
||||
"techage_tubeta4_tube.png",
|
||||
"techage_tube_hole.png",
|
||||
"techage_tube_hole.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
if not Tube: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)
|
||||
Tube:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, -2/8, -4/8, 2/8, 2/8, 4/8},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/4, -1/2, 1/4, 1/4, 1/2 },
|
||||
},
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy=2, cracky=3},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_tubeA", {
|
||||
description = S("TA4 Tube"),
|
||||
tiles = { -- Top, base, right, left, front, back
|
||||
"techage_tubeta4_knee2.png",
|
||||
"techage_tubeta4_hole2.png^[transformR180",
|
||||
"techage_tubeta4_knee.png^[transformR270",
|
||||
"techage_tubeta4_knee.png",
|
||||
"techage_tubeta4_knee2.png",
|
||||
"techage_tubeta4_hole2.png",
|
||||
},
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Tube:after_dig_tube(pos, oldnode, oldmetadata)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, -4/8, -2/8, 2/8, 2/8, 2/8},
|
||||
{-2/8, -2/8, -4/8, 2/8, 2/8, -2/8},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = { -1/4, -1/2, -1/2, 1/4, 1/4, 1/4 },
|
||||
},
|
||||
on_rotate = screwdriver.disallow,
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy=2, cracky=3, not_in_creative_inventory=1},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "techage:ta4_tubeS",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_tubeS 6",
|
||||
recipe = {
|
||||
{"dye:blue", "", "basic_materials:plastic_sheet"},
|
||||
{"", "basic_materials:plastic_sheet", ""},
|
||||
{"basic_materials:plastic_sheet", "", "techage:aluminum"},
|
||||
},
|
||||
})
|
||||
|
||||
techage.TA4tubes = {
|
||||
["techage:ta4_tubeS"] = true,
|
||||
["techage:ta4_tubeA"] = true,
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Wind turbine helper function
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
|
||||
local OCEAN = "ocean"
|
||||
|
||||
if minetest.global_exists("asuna") then
|
||||
OCEAN = "below"
|
||||
end
|
||||
|
||||
local function chat_message(player_name, msg)
|
||||
if player_name then
|
||||
minetest.chat_send_player(player_name, S("[TA4 Wind Turbine]").." "..msg)
|
||||
end
|
||||
return false, msg
|
||||
end
|
||||
|
||||
-- num_turbines is the mx number of valid wind turbines. In the case of a tool
|
||||
-- it should be 0, in case of the rotor: 1
|
||||
function techage.valid_place_for_windturbine(pos, player_name, num_turbines)
|
||||
local pos1, pos2, num
|
||||
|
||||
-- Check if occean (only for tool)
|
||||
if num_turbines == 0 and pos.y ~= 1 then
|
||||
return chat_message(player_name, S("This is not the surface of the ocean!"))
|
||||
end
|
||||
local node = minetest.get_node(pos)
|
||||
if num_turbines == 0 and node.name ~= "default:water_source" then
|
||||
return chat_message(player_name, S("This is no ocean water!"))
|
||||
end
|
||||
local data = minetest.get_biome_data({x=pos.x, y=-2, z=pos.z})
|
||||
if data then
|
||||
local name = minetest.get_biome_name(data.biome)
|
||||
if not string.find(name, OCEAN) then
|
||||
return chat_message(player_name, S("This is a").." "..name.." "..S("biome and no ocean!"))
|
||||
end
|
||||
end
|
||||
-- check the space over ocean
|
||||
pos1 = {x=pos.x-20, y=2, z=pos.z-20}
|
||||
pos2 = {x=pos.x+20, y=22, z=pos.z+20}
|
||||
num = #minetest.find_nodes_in_area(pos1, pos2, {"air", "ignore"})
|
||||
if num < (41 * 41 * 21 * 0.9) then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
return chat_message(player_name,
|
||||
S("Here is not enough wind\n(A free air space of 41x41x21 m is necessary)!"))
|
||||
end
|
||||
-- Check for water surface (occean)
|
||||
pos1 = {x=pos.x-20, y=1, z=pos.z-20}
|
||||
pos2 = {x=pos.x+20, y=1, z=pos.z+20}
|
||||
num = #minetest.find_nodes_in_area(pos1, pos2,
|
||||
{"default:water_source", "default:water_flowing", "ignore"})
|
||||
|
||||
if num < (41*41 * 0.8) then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
return chat_message(player_name, S("Here is not enough water (41x41 m)!"))
|
||||
end
|
||||
-- Check for next wind turbine
|
||||
pos1 = {x=pos.x-13, y=2, z=pos.z-13}
|
||||
pos2 = {x=pos.x+13, y=22, z=pos.z+13}
|
||||
|
||||
num = #minetest.find_nodes_in_area(pos1, pos2, {"techage:ta4_wind_turbine"})
|
||||
if num > num_turbines then
|
||||
techage.mark_region(player_name, pos1, pos2, "")
|
||||
return chat_message(player_name, S("The next wind turbines is too close!"))
|
||||
end
|
||||
|
||||
if num_turbines == 0 then
|
||||
chat_message(player_name, minetest.pos_to_string(pos).." "..
|
||||
S("is a suitable place for a wind turbine!"))
|
||||
end
|
||||
return true, "ok"
|
||||
end
|
@ -1,60 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
K/V Store for the Beduino controller
|
||||
|
||||
]]--
|
||||
|
||||
local COSTS = 400
|
||||
|
||||
local function ta_kv_init(cpu_pos, address, regA, regB, regC)
|
||||
local nvm = techage.get_nvm(cpu_pos)
|
||||
nvm.kv_store = {}
|
||||
return 1, COSTS
|
||||
end
|
||||
|
||||
local function ta_kv_add(cpu_pos, address, regA, regB, regC)
|
||||
local nvm = techage.get_nvm(cpu_pos)
|
||||
local text = vm16.read_ascii(cpu_pos, regA, 32)
|
||||
nvm.kv_store[text] = regB
|
||||
return 1, COSTS
|
||||
end
|
||||
|
||||
local function ta_kv_get(cpu_pos, address, regA, regB, regC)
|
||||
local nvm = techage.get_nvm(cpu_pos)
|
||||
local text = vm16.read_ascii(cpu_pos, regA, 32)
|
||||
return nvm.kv_store[text] or 0, COSTS
|
||||
end
|
||||
|
||||
local kvstore_c = [[
|
||||
// Initialize the key/value store
|
||||
func ta_kv_init() {
|
||||
return system(0x140, 0);
|
||||
}
|
||||
|
||||
// Add a key/value pair to the store
|
||||
func ta_kv_add(key_str, value) {
|
||||
return system(0x141, key_str, value);
|
||||
}
|
||||
|
||||
// Returns the value for the given key string
|
||||
func ta_kv_get(key_str) {
|
||||
return system(0x142, key_str);
|
||||
}
|
||||
]]
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
if minetest.global_exists("beduino") and minetest.global_exists("vm16") then
|
||||
beduino.lib.register_SystemHandler(0x140, ta_kv_init)
|
||||
beduino.lib.register_SystemHandler(0x141, ta_kv_add)
|
||||
beduino.lib.register_SystemHandler(0x142, ta_kv_get)
|
||||
vm16.register_ro_file("beduino", "lib/ta_kvstore.c", kvstore_c)
|
||||
end
|
||||
end)
|
@ -1,181 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Chest Cart
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local MP = minetest.get_modpath("minecart")
|
||||
|
||||
local Tube = techage.Tube
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if clicker and clicker:is_player() then
|
||||
if M(pos):get_int("userID") == 0 then
|
||||
minecart.show_formspec(pos, clicker)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function formspec()
|
||||
return "size[8,6]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"list[context;main;3,0;2,2;]"..
|
||||
"list[current_player;main;0,2.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local owner = M(pos):get_string("owner")
|
||||
if owner ~= "" and owner ~= player:get_player_name() then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
local owner = M(pos):get_string("owner")
|
||||
if owner ~= "" and owner ~= player:get_player_name() then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
minetest.register_node("techage:chest_cart", {
|
||||
description = S("TA Chest Cart"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_chest_cart_top.png",
|
||||
"techage_chest_cart_bottom.png",
|
||||
"techage_chest_cart_side.png",
|
||||
"techage_chest_cart_side.png",
|
||||
"techage_chest_cart_front.png",
|
||||
"techage_chest_cart_front.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-7/16, 3/16, -7/16, 7/16, 8/16, 7/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, 3/16, 8/16},
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, crumbly = 2, choppy = 2},
|
||||
node_placement_prediction = "",
|
||||
diggable = false,
|
||||
|
||||
on_place = minecart.on_nodecart_place,
|
||||
on_punch = minecart.on_nodecart_punch,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
on_rightclick = on_rightclick,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 4)
|
||||
if placer and placer:is_player() then
|
||||
minecart.show_formspec(pos, placer)
|
||||
else
|
||||
M(pos):set_string("formspec", formspec())
|
||||
end
|
||||
end,
|
||||
|
||||
set_cargo = function(pos, data)
|
||||
local inv = M(pos):get_inventory()
|
||||
for idx, stack in ipairs(data) do
|
||||
inv:set_stack("main", idx, stack)
|
||||
end
|
||||
end,
|
||||
|
||||
get_cargo = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
local data = {}
|
||||
for idx = 1, 4 do
|
||||
local stack = inv:get_stack("main", idx)
|
||||
data[idx] = {name = stack:get_name(), count = stack:get_count()}
|
||||
end
|
||||
return data
|
||||
end,
|
||||
|
||||
has_cargo = function(pos)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
return not inv:is_empty("main")
|
||||
end
|
||||
})
|
||||
|
||||
minecart.register_cart_entity("techage:chest_cart_entity", "techage:chest_cart", "chest", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
visual = "wielditem",
|
||||
textures = {"techage:chest_cart"},
|
||||
visual_size = {x=0.66, y=0.66, z=0.66},
|
||||
static_save = false,
|
||||
},
|
||||
})
|
||||
|
||||
techage.register_node({"techage:chest_cart"}, {
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
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
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_inv_state(inv, "main")
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
if topic == 131 then -- Chest State
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return 0, {techage.get_inv_state_num(inv, "main")}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
Tube:set_valid_sides("techage:chest_cart", {"L", "R", "F", "B"})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:chest_cart",
|
||||
recipe = {
|
||||
{"default:junglewood", "default:chest_locked", "default:junglewood"},
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
},
|
||||
})
|
@ -1,176 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Tank Cart
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local Pipe = techage.LiquidPipe
|
||||
local MP = minetest.get_modpath("minecart")
|
||||
|
||||
local liquid = networks.liquid
|
||||
local CAPACITY = 200
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
if clicker and clicker:is_player() then
|
||||
if M(pos):get_int("userID") == 0 then
|
||||
minecart.show_formspec(pos, clicker)
|
||||
else
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
minetest.get_node_timer(pos):start(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
if techage.is_activeformspec(pos) then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function peek_liquid(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
return liquid.srv_peek(nvm)
|
||||
end
|
||||
|
||||
local function take_liquid(pos, indir, name, amount)
|
||||
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", techage.liquid.formspec(pos, nvm))
|
||||
end
|
||||
return amount, name
|
||||
end
|
||||
|
||||
local function put_liquid(pos, indir, name, amount)
|
||||
-- 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 leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
return amount
|
||||
end
|
||||
|
||||
local function untake_liquid(pos, indir, name, amount)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
|
||||
minetest.register_node("techage:tank_cart", {
|
||||
description = S("TA Tank Cart"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_tank_cart_top.png",
|
||||
"techage_tank_cart_bottom.png",
|
||||
"techage_tank_cart_side.png",
|
||||
"techage_tank_cart_side.png",
|
||||
"techage_tank_cart_front.png",
|
||||
"techage_tank_cart_front.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-3/16, 7/16, -3/16, 3/16, 8/16, 3/16},
|
||||
{-7/16, 3/16, -7/16, 7/16, 7/16, 7/16},
|
||||
{-8/16, -8/16, -8/16, 8/16, 3/16, 8/16},
|
||||
},
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {cracky = 2, crumbly = 2, choppy = 2},
|
||||
node_placement_prediction = "",
|
||||
diggable = false,
|
||||
|
||||
on_place = minecart.on_nodecart_place,
|
||||
on_punch = minecart.on_nodecart_punch,
|
||||
|
||||
after_place_node = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = nvm.liquid or {}
|
||||
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
|
||||
-- Delete the network between pump and cart
|
||||
Pipe:after_dig_node(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
|
||||
set_cargo = function(pos, data)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.liquid = data
|
||||
end,
|
||||
|
||||
get_cargo = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local data = nvm.liquid
|
||||
nvm.liquid = {}
|
||||
return data
|
||||
end,
|
||||
|
||||
has_cargo = function(pos)
|
||||
return not techage.liquid.is_empty(pos)
|
||||
end,
|
||||
|
||||
on_timer = node_timer,
|
||||
on_rightclick = on_rightclick,
|
||||
})
|
||||
|
||||
techage.register_node({"techage:tank_cart"}, techage.liquid.recv_message)
|
||||
|
||||
liquid.register_nodes({"techage:tank_cart"},
|
||||
Pipe, "tank", {"U"}, {
|
||||
capa = CAPACITY,
|
||||
peek = peek_liquid,
|
||||
put = put_liquid,
|
||||
take = take_liquid,
|
||||
untake = untake_liquid,
|
||||
}
|
||||
)
|
||||
|
||||
minecart.register_cart_entity("techage:tank_cart_entity", "techage:tank_cart", "tank", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
visual = "wielditem",
|
||||
textures = {"techage:tank_cart"},
|
||||
visual_size = {x=0.66, y=0.66, z=0.66},
|
||||
static_save = false,
|
||||
},
|
||||
only_dig_if_empty = 1,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:tank_cart",
|
||||
recipe = {
|
||||
{"default:junglewood", "techage:ta3_tank", "default:junglewood"},
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
},
|
||||
})
|
@ -1,394 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Doser
|
||||
|
||||
]]--
|
||||
|
||||
local S2P = minetest.string_to_pos
|
||||
local P2S = minetest.pos_to_string
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
local recipes = techage.recipes
|
||||
|
||||
local Liquids = {} -- {hash(pos) = {name = outdir},...}
|
||||
|
||||
local STANDBY_TICKS = 2
|
||||
local COUNTDOWN_TICKS = 3
|
||||
local CYCLE_TIME = 10
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return "size[6,3.6]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
|
||||
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Doser")).."]"..
|
||||
recipes.formspec(0.1, 0.8, "ta4_doser", nvm)..
|
||||
"image_button[5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[5,2;1,1;"..self:get_state_tooltip(nvm).."]"
|
||||
end
|
||||
|
||||
local function get_liquids(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
if Liquids[hash] then
|
||||
return Liquids[hash]
|
||||
end
|
||||
-- determine the available input liquids
|
||||
local tbl = {}
|
||||
for outdir = 1,4 do
|
||||
local name, num = liquid.peek(pos, Pipe, outdir)
|
||||
if name then
|
||||
tbl[name] = outdir
|
||||
end
|
||||
end
|
||||
Liquids[hash] = tbl
|
||||
return Liquids[hash]
|
||||
end
|
||||
|
||||
local function del_liquids(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
Liquids[hash] = nil
|
||||
end
|
||||
|
||||
-- if liquids are missing, update the cached liquid table
|
||||
local function reload_liquids(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
-- determine the available input liquids
|
||||
local tbl = {}
|
||||
for outdir = 1,4 do
|
||||
local name, num = liquid.peek(pos, Pipe, outdir)
|
||||
if name then
|
||||
tbl[name] = outdir
|
||||
end
|
||||
end
|
||||
Liquids[hash] = tbl
|
||||
return Liquids[hash]
|
||||
end
|
||||
|
||||
local function reactor_cmnd(pos, cmnd, payload)
|
||||
return techage.transfer(
|
||||
pos,
|
||||
6, -- outdir
|
||||
cmnd, -- topic
|
||||
payload, -- payload
|
||||
Pipe, -- network
|
||||
{"techage:ta4_reactor_fillerpipe"})
|
||||
end
|
||||
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
-- check reactor
|
||||
local res = reactor_cmnd(pos, "check")
|
||||
if not res then
|
||||
return S("reactor defect")
|
||||
end
|
||||
res = reactor_cmnd(pos, "can_start")
|
||||
if not res then
|
||||
return S("reactor defect or no power")
|
||||
end
|
||||
local recipe = recipes.get(nvm, "ta4_doser")
|
||||
if recipe.catalyst then
|
||||
res = reactor_cmnd(pos, "catalyst")
|
||||
if not res or res == "" then
|
||||
return S("catalyst missing")
|
||||
end
|
||||
if res ~= recipe.catalyst then
|
||||
return S("wrong catalyst")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function start_node(pos, nvm, state)
|
||||
reactor_cmnd(pos, "start")
|
||||
del_liquids(pos)
|
||||
nvm.running = true
|
||||
end
|
||||
|
||||
local function stop_node(pos, nvm, state)
|
||||
reactor_cmnd(pos, "stop")
|
||||
nvm.running = false
|
||||
end
|
||||
|
||||
local State = techage.NodeStates:new({
|
||||
node_name_passive = "techage:ta4_doser",
|
||||
node_name_active = "techage:ta4_doser_on",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec_func = formspec,
|
||||
infotext_name = "TA4 Doser",
|
||||
can_start = can_start,
|
||||
start_node = start_node,
|
||||
stop_node = stop_node,
|
||||
})
|
||||
|
||||
local function untake(pos, taken)
|
||||
for _,item in pairs(taken) do
|
||||
liquid.untake(pos, Pipe, item.outdir, item.name, item.num)
|
||||
end
|
||||
end
|
||||
|
||||
local function dosing(pos, nvm, elapsed)
|
||||
-- trigger reactor (power)
|
||||
if not reactor_cmnd(pos, "power") then
|
||||
if not nvm.techage_countdown or nvm.techage_countdown < 3 then
|
||||
reactor_cmnd(pos, "stop")
|
||||
State:nopower(pos, nvm, S("reactor has no power"))
|
||||
return
|
||||
end
|
||||
State:idle(pos, nvm)
|
||||
return
|
||||
end
|
||||
-- available liquids
|
||||
local liquids = get_liquids(pos)
|
||||
local recipe = recipes.get(nvm, "ta4_doser")
|
||||
if not liquids or not recipe then return end
|
||||
-- check from time to time
|
||||
nvm.check_cnt = (nvm.check_cnt or 0) + 1
|
||||
if nvm.check_cnt >= 4 then
|
||||
nvm.check_cnt = 0
|
||||
local res = reactor_cmnd(pos, "check")
|
||||
if not res then
|
||||
State:fault(pos, nvm, S("reactor defect"))
|
||||
reactor_cmnd(pos, "stop")
|
||||
return
|
||||
end
|
||||
if recipe.catalyst then
|
||||
res = reactor_cmnd(pos, "catalyst")
|
||||
if not res then
|
||||
State:fault(pos, nvm, S("catalyst missing"))
|
||||
reactor_cmnd(pos, "stop")
|
||||
return
|
||||
end
|
||||
if res ~= recipe.catalyst then
|
||||
State:fault(pos, nvm, S("wrong catalyst"))
|
||||
reactor_cmnd(pos, "stop")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- check leftover
|
||||
local leftover
|
||||
local mem = techage.get_mem(pos)
|
||||
if mem.waste_leftover then
|
||||
leftover = reactor_cmnd(pos, "waste", {
|
||||
name = mem.waste_leftover.name,
|
||||
amount = mem.waste_leftover.num}) or mem.waste_leftover.num
|
||||
if leftover > 0 then
|
||||
mem.waste_leftover.num = leftover
|
||||
State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
mem.waste_leftover = nil
|
||||
end
|
||||
if mem.output_leftover then
|
||||
leftover = reactor_cmnd(pos, "output", {
|
||||
name = mem.output_leftover.name,
|
||||
amount = mem.output_leftover.num}) or mem.output_leftover.num
|
||||
if leftover > 0 then
|
||||
mem.output_leftover.num = leftover
|
||||
State:blocked(pos, nvm)
|
||||
return
|
||||
end
|
||||
mem.output_leftover = nil
|
||||
end
|
||||
|
||||
-- inputs
|
||||
local taken = {}
|
||||
mem.dbg_cycles = (mem.dbg_cycles or 0) - 1
|
||||
|
||||
for _,item in pairs(recipe.input) do
|
||||
if item.name ~= "" then
|
||||
local outdir = liquids[item.name] or reload_liquids(pos)[item.name]
|
||||
if not outdir then
|
||||
State:standby(pos, nvm)
|
||||
reactor_cmnd(pos, "stop")
|
||||
untake(pos, taken)
|
||||
return
|
||||
end
|
||||
local num = liquid.take(pos, Pipe, outdir, item.name, item.num, mem.dbg_cycles > 0)
|
||||
if num < item.num then
|
||||
taken[#taken + 1] = {outdir = outdir, name = item.name, num = num}
|
||||
State:standby(pos, nvm)
|
||||
reactor_cmnd(pos, "stop")
|
||||
untake(pos, taken)
|
||||
return
|
||||
end
|
||||
taken[#taken + 1] = {outdir = outdir, name = item.name, num = item.num}
|
||||
end
|
||||
end
|
||||
-- waste
|
||||
if recipe.waste.name ~= "" then
|
||||
leftover = reactor_cmnd(pos, "waste", {
|
||||
name = recipe.waste.name,
|
||||
amount = recipe.waste.num}) or recipe.waste.num
|
||||
if leftover > 0 then
|
||||
mem.waste_leftover = {name = recipe.waste.name, num = leftover}
|
||||
mem.output_leftover = {name = recipe.output.name, num = recipe.output.num}
|
||||
State:blocked(pos, nvm)
|
||||
reactor_cmnd(pos, "stop")
|
||||
return
|
||||
end
|
||||
end
|
||||
-- output
|
||||
leftover = reactor_cmnd(pos, "output", {
|
||||
name = recipe.output.name,
|
||||
amount = recipe.output.num}) or recipe.output.num
|
||||
if leftover > 0 then
|
||||
mem.output_leftover = {name = recipe.output.name, num = leftover}
|
||||
State:blocked(pos, nvm)
|
||||
reactor_cmnd(pos, "stop")
|
||||
return
|
||||
end
|
||||
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
dosing(pos, nvm, elapsed)
|
||||
return State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if not nvm.running then
|
||||
if recipes.on_receive_fields(pos, formname, fields, player) then
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.waste_leftover = nil
|
||||
mem.output_leftover = nil
|
||||
end
|
||||
end
|
||||
local mem = techage.get_mem(pos)
|
||||
mem.dbg_cycles = 5
|
||||
State:state_button_event(pos, nvm, fields)
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_doser", {
|
||||
description = S("TA4 Doser"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png^techage_appl_hole_pipe.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_pump_up.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local number = techage.add_node(pos, "techage:ta4_doser")
|
||||
meta:set_string("node_number", number)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec(State, pos, nvm))
|
||||
meta:set_string("infotext", S("TA4 Doser").." "..number)
|
||||
State:node_init(pos, nvm, number)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
tubelib2_on_update2 = function(pos, dir, tlib2, node)
|
||||
liquid.update_network(pos, dir, tlib2, node)
|
||||
del_liquids(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
techage.remove_node(pos, oldnode, oldmetadata)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
on_timer = node_timer,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_doser_on", {
|
||||
description = S("TA4 Doser"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta4.png^techage_frame_ta4_top.png^techage_appl_hole_pipe.png",
|
||||
"techage_filling_ta4.png^techage_frame_ta4.png",
|
||||
{
|
||||
name = "techage_filling8_ta4.png^techage_frame8_ta4.png^techage_appl_pump_up8.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
tubelib2_on_update2 = function(pos, dir, tlib2, node)
|
||||
liquid.update_network(pos, dir, tlib2, node)
|
||||
del_liquids(pos)
|
||||
end,
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
on_timer = node_timer,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
diggable = false,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:ta4_doser", "techage:ta4_doser_on"}, Pipe, "pump", nil, {})
|
||||
|
||||
techage.register_node({"techage:ta4_doser", "techage:ta4_doser_on"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
if topic == "recipe" then
|
||||
techage.recipes.set_recipe(pos, "ta4_doser", payload)
|
||||
return true
|
||||
else
|
||||
return State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
return State:on_beduino_request_data(pos, topic, payload)
|
||||
end,
|
||||
})
|
||||
|
||||
techage.recipes.register_craft_type("ta4_doser", {
|
||||
description = S("TA4 Reactor"),
|
||||
icon = 'techage_reactor_filler_plan.png',
|
||||
width = 2,
|
||||
height = 2,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:ta4_doser",
|
||||
recipe = {
|
||||
{"", "techage:ta3_pipeS", ""},
|
||||
{"techage:ta3_pipeS", "techage:t4_pump", "techage:ta3_pipeS"},
|
||||
{"", "techage:ta4_wlanchip", ""},
|
||||
},
|
||||
})
|
@ -1,209 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
Copyright (C) 2020 Thomas S.
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Liquid Filter
|
||||
|
||||
]]--
|
||||
|
||||
-- For now, the Red Mud -> Lye/Desert Cobble recipe is hardcoded.
|
||||
-- If necessary, this can be adjusted later.
|
||||
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
|
||||
-- Checks if the filter structure is ok and returns the amount of gravel
|
||||
local function checkStructure(pos)
|
||||
local pos1_outer = {x=pos.x-2,y=pos.y-7,z=pos.z-2}
|
||||
local pos2_outer = {x=pos.x+2,y=pos.y,z=pos.z+2}
|
||||
local pos1_inner = {x=pos.x-1,y=pos.y-1,z=pos.z-1}
|
||||
local pos2_inner = {x=pos.x+1,y=pos.y-7,z=pos.z+1}
|
||||
local pos1_top = {x=pos.x-1,y=pos.y,z=pos.z-1}
|
||||
local pos2_top = {x=pos.x+1,y=pos.y,z=pos.z+1}
|
||||
local pos1_bottom = {x=pos.x-2,y=pos.y-8,z=pos.z-2}
|
||||
local pos2_bottom = {x=pos.x+2,y=pos.y-8,z=pos.z+2}
|
||||
|
||||
|
||||
local gravel = minetest.find_nodes_in_area(pos1_inner, pos2_inner, {"default:gravel"})
|
||||
|
||||
local _, inner = minetest.find_nodes_in_area(pos1_inner, pos2_inner, {
|
||||
"default:desert_cobble"
|
||||
})
|
||||
if #gravel + (inner["default:desert_cobble"] or 0) ~= 63 then -- 7x3x3=63
|
||||
return false, gravel
|
||||
end
|
||||
|
||||
local _, outer = minetest.find_nodes_in_area(pos1_outer, pos2_outer, {
|
||||
"basic_materials:concrete_block",
|
||||
"default:obsidian_glass"
|
||||
})
|
||||
|
||||
-- + 4x7=28 (corners)
|
||||
-- + 5x5-3x3=16 (top ring)
|
||||
-- ------------------------------
|
||||
-- = 44 (total concrete)
|
||||
if outer["basic_materials:concrete_block"] ~= 44 then
|
||||
return false, gravel
|
||||
end
|
||||
if outer["default:obsidian_glass"] ~= 84 then -- 4x7x3=84
|
||||
return false, gravel
|
||||
end
|
||||
|
||||
local _,top = minetest.find_nodes_in_area(pos1_top, pos2_top, {"air"})
|
||||
if top["air"] ~= 8 then
|
||||
return false, gravel
|
||||
end
|
||||
|
||||
local _,bottom = minetest.find_nodes_in_area(pos1_bottom, pos2_bottom, {
|
||||
"basic_materials:concrete_block",
|
||||
"techage:ta3_pipe_wall_entry"
|
||||
})
|
||||
if bottom["basic_materials:concrete_block"] ~= 22 or bottom["techage:ta3_pipe_wall_entry"] ~= 2 then
|
||||
return false, gravel
|
||||
end
|
||||
|
||||
if minetest.get_node({x=pos.x,y=pos.y-8,z=pos.z}).name ~= "techage:ta4_liquid_filter_sink" then
|
||||
return false, gravel
|
||||
end
|
||||
|
||||
return true, gravel
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_liquid_filter_filler", {
|
||||
description = S("TA4 Liquid Filter Filler"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"basic_materials_concrete_block.png^techage_gaspipe_hole.png",
|
||||
"basic_materials_concrete_block.png^techage_liquid_filter_filler_bottom.png",
|
||||
"basic_materials_concrete_block.png^techage_liquid_filter_filler.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-6/8, -0.5, -6/8, 6/8, -0.25, 6/8},
|
||||
{-7/16, -0.25, -7/16, 7/16, 0, 7/16},
|
||||
{-1/8, 0, -1/8, 1/8, 13/32, 1/8},
|
||||
{-2/8, 13/32, -2/8, 2/8, 0.5, 2/8},
|
||||
},
|
||||
},
|
||||
after_place_node = function(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:ta4_liquid_filter_filler"},
|
||||
Pipe, "tank", {"U"}, {
|
||||
capa = 1,
|
||||
peek = function(...) return nil end,
|
||||
put = function(pos, indir, name, amount)
|
||||
local structure_ok, gravel = checkStructure(pos)
|
||||
if name ~= "techage:redmud" then
|
||||
return amount
|
||||
end
|
||||
if not structure_ok then
|
||||
return amount
|
||||
end
|
||||
if #gravel < 33 then
|
||||
return amount
|
||||
end
|
||||
if math.random() < 0.5 then
|
||||
local out_pos = {x=pos.x,y=pos.y-8,z=pos.z}
|
||||
local leftover = liquid.put(out_pos, Pipe, networks.side_to_outdir(out_pos, "R"), "techage:lye", 1)
|
||||
if leftover > 0 then
|
||||
return amount
|
||||
end
|
||||
else
|
||||
minetest.swap_node(gravel[math.random(#gravel)], {name = "default:desert_cobble"})
|
||||
end
|
||||
return amount - 1
|
||||
end,
|
||||
take = function(...) return 0 end,
|
||||
untake = function(pos, outdir, name, amount, player_name)
|
||||
return amount
|
||||
end,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
minetest.register_node("techage:ta4_liquid_filter_sink", {
|
||||
description = S("TA4 Liquid Filter Sink"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"basic_materials_concrete_block.png^techage_appl_arrow.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png^techage_appl_hole_pipe.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
"basic_materials_concrete_block.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 3/16, 0.5},
|
||||
{-0.5, 3/16, -0.5, 0.5, 5/16, -0.25},
|
||||
{0.25, 3/16, -0.5, 0.5, 5/16, 0.5},
|
||||
{-0.5, 3/16, 0.25, 0.5, 5/16, 0.5},
|
||||
{-0.5, 3/16, -0.5, -0.25, 5/16, 0.5}
|
||||
},
|
||||
},
|
||||
after_place_node = function(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Pipe:after_dig_node(pos)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:ta4_liquid_filter_sink"},
|
||||
Pipe, "pump", {"R"}, {}
|
||||
)
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_liquid_filter_filler',
|
||||
recipe = {
|
||||
{'', 'techage:ta3_pipeS', ''},
|
||||
{'basic_materials:concrete_block', 'basic_materials:concrete_block', 'basic_materials:concrete_block'},
|
||||
{'', 'default:steel_ingot', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_liquid_filter_sink 2',
|
||||
recipe = {
|
||||
{'basic_materials:concrete_block', '', 'basic_materials:concrete_block'},
|
||||
{'basic_materials:concrete_block', 'techage:ta3_pipeS', 'techage:ta3_pipeS'},
|
||||
{'basic_materials:concrete_block', 'basic_materials:concrete_block', 'basic_materials:concrete_block'},
|
||||
}
|
||||
})
|
@ -1,226 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Reactor
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local M = minetest.get_meta
|
||||
local Pipe = techage.LiquidPipe
|
||||
local Cable = techage.ElectricCable
|
||||
local liquid = networks.liquid
|
||||
|
||||
minetest.register_node("techage:ta4_reactor_fillerpipe", {
|
||||
description = S("TA4 Reactor Filler Pipe"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_reactor_filler_top.png",
|
||||
"techage_reactor_filler_top.png",
|
||||
"techage_reactor_filler_side.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-2/8, 13/32, -2/8, 2/8, 4/8, 2/8},
|
||||
{-1/8, 0/8, -1/8, 1/8, 4/8, 1/8},
|
||||
{-5/16, 0/8, -5/16, 5/16, 2/8, 5/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-2/8, 0/8, -2/8, 2/8, 4/8, 2/8},
|
||||
},
|
||||
after_place_node = function(pos)
|
||||
local pos1 = {x = pos.x, y = pos.y-1, z = pos.z}
|
||||
if minetest.get_node(pos1).name == "air" then
|
||||
local node = minetest.get_node(pos)
|
||||
minetest.remove_node(pos)
|
||||
minetest.set_node(pos1, node)
|
||||
Pipe:after_place_node(pos1)
|
||||
end
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Pipe:after_dig_node(pos)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
local function stand_cmnd(pos, cmnd, payload)
|
||||
return techage.transfer(
|
||||
{x = pos.x, y = pos.y-1, z = pos.z},
|
||||
5, -- outdir
|
||||
cmnd, -- topic
|
||||
payload, -- payload
|
||||
nil, -- network
|
||||
{"techage:ta4_reactor_stand"})
|
||||
end
|
||||
|
||||
local function base_waste(pos, payload)
|
||||
local pos2 = {x = pos.x, y = pos.y-3, z = pos.z}
|
||||
local outdir = M(pos2):get_int("outdir")
|
||||
return liquid.put(pos2, Pipe, outdir, payload.name, payload.amount, payload.player_name)
|
||||
end
|
||||
|
||||
-- controlled by the doser
|
||||
techage.register_node({"techage:ta4_reactor_fillerpipe"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
if topic == "check" then
|
||||
local pos2,node = Pipe:get_node(pos, 5)
|
||||
if not node or node.name ~= "techage:ta4_reactor" then
|
||||
return false
|
||||
end
|
||||
pos2,node = Pipe:get_node(pos2, 5)
|
||||
if not node or node.name ~= "techage:ta4_reactor_stand" then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
elseif topic == "waste" then
|
||||
return base_waste(pos, payload or {})
|
||||
elseif topic == "catalyst" then
|
||||
local pos2,node = Pipe:get_node(pos, 5)
|
||||
if not node or node.name ~= "techage:ta4_reactor" then
|
||||
return
|
||||
end
|
||||
local inv = M(pos2):get_inventory()
|
||||
local stack = inv:get_stack("main", 1)
|
||||
return stack and stack:get_name()
|
||||
else
|
||||
return stand_cmnd(pos, topic, payload or {})
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:ta4_reactor_fillerpipe"}, Pipe, "tank", {"U"}, {})
|
||||
|
||||
local function formspec()
|
||||
local title = S("TA4 Reactor")
|
||||
return "size[8,6]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;7.8,0.5;#c6e8ff]"..
|
||||
"label[3,-0.1;"..minetest.colorize("#000000", title).."]"..
|
||||
"label[4.5,1.2;"..S("Catalyst").."]"..
|
||||
"list[context;main;3.5,1;1,1;]"..
|
||||
"list[current_player;main;0,2.3;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
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
|
||||
return 1
|
||||
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
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_reactor", {
|
||||
description = S("TA4 Reactor"),
|
||||
tiles = {"techage_reactor_side.png"},
|
||||
drawtype = "mesh",
|
||||
mesh = "techage_cylinder_12h.obj",
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -23/32, -1/2, 1/2, 32/32, 1/2},
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -23/32, -1/2, 1/2, 32/32, 1/2},
|
||||
},
|
||||
after_place_node = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
M(pos):set_string("formspec", formspec())
|
||||
end,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
techage.register_node({"techage:ta4_reactor"}, {
|
||||
on_inv_request = function(pos, in_dir, access_type)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_inventory(), "main"
|
||||
end,
|
||||
on_pull_item = function(pos, in_dir, num, item_name)
|
||||
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)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "main", stack)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_reactor',
|
||||
recipe = {
|
||||
{'default:steel_ingot', 'techage:ta3_pipeS', 'default:steel_ingot'},
|
||||
{'techage:iron_ingot', '', 'techage:iron_ingot'},
|
||||
{'default:steel_ingot', 'techage:ta3_pipeS', 'default:steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_reactor_fillerpipe',
|
||||
recipe = {
|
||||
{'', '', ''},
|
||||
{'', 'techage:ta3_pipeS', ''},
|
||||
{'default:steel_ingot', 'basic_materials:motor', 'default:steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Upgrade reactor",
|
||||
name = "techage:update_reactor",
|
||||
|
||||
nodenames = {
|
||||
"techage:ta4_reactor",
|
||||
},
|
||||
|
||||
run_at_every_load = true,
|
||||
|
||||
action = function(pos, node)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 1)
|
||||
M(pos):set_string("formspec", formspec())
|
||||
end,
|
||||
})
|
@ -1,209 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2021 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA4 Reactor Stand and Base
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local M = minetest.get_meta
|
||||
local Cable = techage.ElectricCable
|
||||
local Pipe = techage.LiquidPipe
|
||||
local power = networks.power
|
||||
local liquid = networks.liquid
|
||||
|
||||
local PWR_NEEDED = 8
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local function play_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.handle or mem.handle == -1 then
|
||||
mem.handle = minetest.sound_play("techage_reactor", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 10,
|
||||
loop = true})
|
||||
if mem.handle == -1 then
|
||||
minetest.after(1, play_sound, pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if mem.handle then
|
||||
minetest.sound_stop(mem.handle)
|
||||
mem.handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function on_power(pos)
|
||||
M(pos):set_string("infotext", S("on"))
|
||||
play_sound(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = true
|
||||
end
|
||||
|
||||
local function on_nopower(pos)
|
||||
M(pos):set_string("infotext", S("no power"))
|
||||
stop_sound(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = false
|
||||
end
|
||||
|
||||
local function is_running(pos, nvm)
|
||||
return nvm.running
|
||||
end
|
||||
|
||||
minetest.register_node("techage:ta4_reactor_stand", {
|
||||
description = S("TA4 Reactor Stand"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_reactor_stand_top.png^[transformR90",
|
||||
"techage_reactor_stand_bottom.png^[transformFY^[transformR270",
|
||||
"techage_reactor_stand_front.png",
|
||||
"techage_reactor_stand_back.png",
|
||||
"techage_reactor_stand_side.png^[transformFX",
|
||||
"techage_reactor_stand_side.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -8/16, 2/16, -8/16, 8/16, 4/16, 8/16 },
|
||||
|
||||
{ -8/16, -8/16, -8/16, -6/16, 8/16, -6/16 },
|
||||
{ 6/16, -8/16, -8/16, 8/16, 8/16, -6/16 },
|
||||
{ -8/16, -8/16, 6/16, -6/16, 8/16, 8/16 },
|
||||
{ 6/16, -8/16, 6/16, 8/16, 8/16, 8/16 },
|
||||
|
||||
{-1/8, -4/8, -1/8, 1/8, 4/8, 1/8},
|
||||
{-4/8, -1/8, -1/8, 4/8, 1/8, 1/8},
|
||||
{-4/8, -1/8, -3/8, -3/8, 1/8, 3/8},
|
||||
{ 3/8, -1/8, -3/8, 4/8, 1/8, 3/8},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-1/2, -1/2, -1/2, 1/2, 1/2, 1/2},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("infotext", S("off"))
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
Pipe:after_place_node(pos)
|
||||
Cable:after_place_node(pos)
|
||||
end,
|
||||
on_timer = function(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
|
||||
if not nvm.running and consumed == PWR_NEEDED then
|
||||
on_power(pos)
|
||||
elseif nvm.running and consumed < PWR_NEEDED then
|
||||
on_nopower(pos)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
Cable:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
-- controlled by the fillerpipe
|
||||
techage.register_node({"techage:ta4_reactor_stand"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "power" then
|
||||
return nvm.running or power.power_available(pos, Cable)
|
||||
elseif topic == "output" then
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
return liquid.put(pos, Pipe, outdir, payload.name, payload.amount, payload.player_name)
|
||||
elseif topic == "can_start" then
|
||||
return power.power_available(pos, Cable)
|
||||
elseif topic == "start" then
|
||||
nvm.running = false
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
M(pos):set_string("infotext", "...")
|
||||
return true
|
||||
elseif topic == "stop" then
|
||||
nvm.has_power = false
|
||||
stop_sound(pos)
|
||||
minetest.get_node_timer(pos):stop()
|
||||
M(pos):set_string("infotext", S("off"))
|
||||
return true
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos, node)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if nvm.has_power then
|
||||
play_sound(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("techage:ta4_reactor_base", {
|
||||
description = S("TA4 Reactor Base"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_concrete.png^techage_appl_arrowXL.png^techage_appl_hole_pipe.png^[transformR270",
|
||||
"techage_concrete.png",
|
||||
"techage_concrete.png^techage_appl_hole_pipe.png",
|
||||
"techage_concrete.png",
|
||||
"techage_concrete.png",
|
||||
"techage_concrete.png",
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
Pipe:after_place_node(pos)
|
||||
end,
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
Pipe:after_dig_node(pos)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:ta4_reactor_base"}, Pipe, "pump", {"R"}, {})
|
||||
liquid.register_nodes({"techage:ta4_reactor_stand"}, Pipe, "pump", {"R"}, {})
|
||||
power.register_nodes({"techage:ta4_reactor_stand"}, Cable, "con", {"L"})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_reactor_stand',
|
||||
recipe = {
|
||||
{'', 'dye:blue', ''},
|
||||
{'basic_materials:steel_bar', 'techage:ta3_pipeS', 'basic_materials:steel_bar'},
|
||||
{'basic_materials:steel_bar', '', 'basic_materials:steel_bar'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'techage:ta4_reactor_base',
|
||||
recipe = {
|
||||
{'basic_materials:concrete_block', '', ''},
|
||||
{'techage:ta3_pipeS', '', ''},
|
||||
{'', '', ''},
|
||||
}
|
||||
})
|
@ -1,67 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Coal Power Station Boiler Base
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Pipe = techage.SteamPipe
|
||||
local networks = techage.networks
|
||||
|
||||
local function after_place_node(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:coalboiler_base", {
|
||||
description = S("TA3 Boiler Base"),
|
||||
tiles = {"techage_coal_boiler_mesh_base.png"},
|
||||
drawtype = "mesh",
|
||||
mesh = "techage_cylinder_12.obj",
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-13/32, -16/32, -13/32, 13/32, 16/32, 13/32},
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
Pipe:add_secondary_node_names({"techage:coalboiler_base"})
|
||||
|
||||
-- for logical communication
|
||||
techage.register_node({"techage:coalboiler_base"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:coalboiler_base",
|
||||
recipe = {
|
||||
{"default:stone", "", "default:stone"},
|
||||
{"techage:iron_ingot", "", "techage:iron_ingot"},
|
||||
{"default:stone", "default:stone", "default:stone"},
|
||||
},
|
||||
})
|
@ -1,110 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Coal Power Station Boiler Top
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local CYCLE_TIME = 4
|
||||
local WATER_CONSUMPTION = 0.1
|
||||
|
||||
local Pipe = techage.SteamPipe
|
||||
local boiler = techage.boiler
|
||||
|
||||
local function steaming(pos, nvm, temp)
|
||||
if temp >= 80 then
|
||||
local wc = WATER_CONSUMPTION * (nvm.power_ratio or 1)
|
||||
nvm.water_level = math.max((nvm.water_level or 0) - wc, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local temp = boiler.water_temperature(pos, nvm)
|
||||
steaming(pos, nvm, temp)
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", boiler.formspec(pos, nvm))
|
||||
end
|
||||
return temp > 20
|
||||
end
|
||||
|
||||
local function after_place_node(pos)
|
||||
local node = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z})
|
||||
if node.name == "techage:coalboiler_base" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", boiler.formspec(pos, nvm))
|
||||
Pipe:after_place_node(pos)
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:coalboiler_top", {
|
||||
description = S("TA3 Boiler Top"),
|
||||
tiles = {"techage_coal_boiler_mesh_top.png"},
|
||||
drawtype = "mesh",
|
||||
mesh = "techage_cylinder_12.obj",
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-13/32, -48/32, -13/32, 13/32, 16/32, 13/32},
|
||||
},
|
||||
|
||||
can_dig = boiler.can_dig,
|
||||
on_timer = node_timer,
|
||||
on_rightclick = boiler.on_rightclick,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
on_punch = boiler.on_punch,
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=1},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
})
|
||||
|
||||
Pipe:add_secondary_node_names({"techage:coalboiler_top"})
|
||||
|
||||
|
||||
techage.register_node({"techage:coalboiler_top"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
if topic == "trigger" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.fire_trigger = true
|
||||
if not minetest.get_node_timer(pos):is_started() then
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end
|
||||
if (nvm.temperature or 20) > 80 then
|
||||
nvm.power_ratio = techage.transfer(pos, "F", "trigger", nil, Pipe, {
|
||||
"techage:turbine", "techage:turbine_on"}) or 0
|
||||
return nvm.power_ratio
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:coalboiler_top",
|
||||
recipe = {
|
||||
{"default:stone", "default:stone", "default:stone"},
|
||||
{"techage:iron_ingot", "", "techage:iron_ingot"},
|
||||
{"default:stone", "", "default:stone"},
|
||||
},
|
||||
})
|
@ -1,133 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Cooler
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Pipe = techage.SteamPipe
|
||||
|
||||
local function transfer(pos, in_dir, topic, payload)
|
||||
return techage.transfer(pos, in_dir, topic, payload, Pipe,
|
||||
{"techage:coalboiler_base"})
|
||||
end
|
||||
|
||||
local function after_place_node(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:cooler", {
|
||||
description = S("TA3 Cooler"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_cooler4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_cooler4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_cooler.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_cooler.png",
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
-- legacy node
|
||||
minetest.register_node("techage:cooler_on", {
|
||||
description = S("TA3 Cooler"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_cooler4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_cooler4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_cooler.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_cooler.png",
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
drop = "techage:cooler",
|
||||
groups = {cracky=2, crumbly=2, choppy=2, not_in_creative_inventory=1},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
Pipe:add_secondary_node_names({"techage:cooler", "techage:cooler_on"})
|
||||
|
||||
-- for logical communication
|
||||
techage.register_node({"techage:cooler", "techage:cooler_on"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
return transfer(pos, in_dir, topic, payload)
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:cooler",
|
||||
recipe = {
|
||||
{"basic_materials:steel_bar", "default:wood", "basic_materials:steel_bar"},
|
||||
{"techage:steam_pipeS", "basic_materials:gear_steel", "techage:steam_pipeS"},
|
||||
{"basic_materials:steel_bar", "default:wood", "basic_materials:steel_bar"},
|
||||
},
|
||||
})
|
@ -1,231 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Coal Power Station Firebox
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local firebox = techage.firebox
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
local BURN_CYCLE_FACTOR = 0.5
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local power = techage.transfer(
|
||||
{x=pos.x, y=pos.y+2, z=pos.z},
|
||||
nil, -- outdir
|
||||
"trigger", -- topic
|
||||
nil, -- payload
|
||||
nil, -- network
|
||||
{"techage:coalboiler_top"} -- nodenames
|
||||
)
|
||||
nvm.burn_cycles = (nvm.burn_cycles or 0) - math.max((power or 0.02), 0.02)
|
||||
if nvm.burn_cycles <= 0 then
|
||||
local taken = firebox.get_fuel(pos)
|
||||
if taken then
|
||||
nvm.burn_cycles = (firebox.Burntime[taken:get_name()] or 1) / CYCLE_TIME * BURN_CYCLE_FACTOR
|
||||
nvm.burn_cycles_total = nvm.burn_cycles
|
||||
else
|
||||
nvm.running = false
|
||||
firebox.set_firehole(pos, false)
|
||||
M(pos):set_string("formspec", firebox.formspec(nvm))
|
||||
return false
|
||||
end
|
||||
end
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", firebox.formspec(nvm))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function start_firebox(pos, nvm)
|
||||
if not nvm.running then
|
||||
nvm.running = true
|
||||
node_timer(pos, 0)
|
||||
firebox.set_firehole(pos, true)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:coalfirebox", {
|
||||
description = S("TA3 Power Station Firebox"),
|
||||
inventory_image = "techage_coal_boiler_inv.png",
|
||||
tiles = {"techage_coal_boiler_mesh_top.png"},
|
||||
drawtype = "mesh",
|
||||
mesh = "techage_cylinder_12.obj",
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-13/32, -16/32, -13/32, 13/32, 16/32, 13/32},
|
||||
},
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
|
||||
on_timer = node_timer,
|
||||
can_dig = firebox.can_dig,
|
||||
allow_metadata_inventory_put = firebox.allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_take = firebox.allow_metadata_inventory_take,
|
||||
on_rightclick = firebox.on_rightclick,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
if firebox.is_free_position(pos, placer:get_player_name()) then
|
||||
techage.add_node(pos, "techage:coalfirebox", true)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = false
|
||||
nvm.burn_cycles = 0
|
||||
local meta = M(pos)
|
||||
meta:set_string("formspec", firebox.formspec(nvm))
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size('fuel', 1)
|
||||
firebox.set_firehole(pos, false)
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
firebox.set_firehole(pos, nil)
|
||||
end,
|
||||
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
start_firebox(pos, nvm)
|
||||
M(pos):set_string("formspec", firebox.formspec(nvm))
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("techage:coalfirehole", {
|
||||
description = S("TA3 Coal Power Station Firebox"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_coal_boiler.png",
|
||||
"techage_coal_boiler.png",
|
||||
"techage_coal_boiler.png",
|
||||
"techage_coal_boiler.png",
|
||||
"techage_coal_boiler.png",
|
||||
"techage_coal_boiler.png^techage_appl_firehole.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-6/16, -6/16, 6/16, 6/16, 6/16, 12/16},
|
||||
},
|
||||
},
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
is_ground_content = false,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
minetest.register_node("techage:coalfirehole_on", {
|
||||
description = S("TA3 Coal Power Station Firebox"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_coal_boiler.png^[colorize:black:80",
|
||||
"techage_coal_boiler.png^[colorize:black:80",
|
||||
"techage_coal_boiler.png^[colorize:black:80",
|
||||
"techage_coal_boiler.png^[colorize:black:80",
|
||||
"techage_coal_boiler.png^[colorize:black:80",
|
||||
{
|
||||
name = "techage_coal_boiler4.png^[colorize:black:80^techage_appl_firehole4.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-6/16, -6/16, 6/16, 6/16, 6/16, 12/16},
|
||||
},
|
||||
},
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
light_source = 8,
|
||||
pointable = false,
|
||||
diggable = false,
|
||||
is_ground_content = false,
|
||||
groups = {not_in_creative_inventory=1},
|
||||
})
|
||||
|
||||
|
||||
techage.register_node({"techage:coalfirebox"}, {
|
||||
on_pull_item = function(pos, in_dir, num)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.get_items(pos, inv, "fuel", num)
|
||||
end,
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
if firebox.Burntime[stack:get_name()] then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local nvm = techage.get_nvm(pos)
|
||||
start_firebox(pos, nvm)
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
end
|
||||
return false
|
||||
end,
|
||||
on_unpull_item = function(pos, in_dir, stack)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
return techage.put_items(inv, "fuel", stack)
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "state" then
|
||||
return nvm.running and "running" or "stopped"
|
||||
elseif topic == "fuel" then
|
||||
return techage.fuel.get_fuel_amount(nvm)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == 128 then
|
||||
return 0, techage.get_node_lvm(pos).name
|
||||
elseif topic == 129 then
|
||||
return 0, {nvm.running and techage.RUNNING or techage.STOPPED}
|
||||
elseif topic == 132 then
|
||||
return 0, {techage.fuel.get_fuel_amount(nvm)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:coalfirebox",
|
||||
recipe = {
|
||||
{'default:stone', 'default:stone', 'default:stone'},
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
||||
{'default:stone', 'default:stone', 'default:stone'},
|
||||
},
|
||||
})
|
@ -1,276 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Power Station Generator
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Cable = techage.ElectricCable
|
||||
local power = networks.power
|
||||
local control = networks.control
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
local STANDBY_TICKS = 4
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local PWR_PERF = 80
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
return techage.generator_formspec(self, pos, nvm, S("Generator"), nvm.provided, PWR_PERF)
|
||||
end
|
||||
|
||||
local function transfer_turbine(pos, topic, payload)
|
||||
return techage.transfer(pos, "L", topic, payload, nil,
|
||||
{"techage:turbine", "techage:turbine_on"})
|
||||
end
|
||||
|
||||
local function can_start(pos, nvm, state)
|
||||
return (nvm.firebox_trigger or 0) > 0 -- by means of firebox
|
||||
end
|
||||
|
||||
local function has_fire(nvm)
|
||||
nvm.firebox_trigger = (nvm.firebox_trigger or 0) - 1
|
||||
return nvm.firebox_trigger > 0
|
||||
end
|
||||
|
||||
local function start_node(pos, nvm, state)
|
||||
local meta = M(pos)
|
||||
nvm.provided = 0
|
||||
local outdir = meta:get_int("outdir")
|
||||
transfer_turbine(pos, "start")
|
||||
power.start_storage_calc(pos, Cable, outdir)
|
||||
techage.evaluate_charge_termination(nvm, meta)
|
||||
end
|
||||
|
||||
local function stop_node(pos, nvm, state)
|
||||
nvm.provided = 0
|
||||
local outdir = M(pos):get_int("outdir")
|
||||
transfer_turbine(pos, "stop")
|
||||
power.start_storage_calc(pos, Cable, outdir)
|
||||
end
|
||||
|
||||
local State = techage.NodeStates:new({
|
||||
node_name_passive = "techage:generator",
|
||||
node_name_active = "techage:generator_on",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec_func = formspec,
|
||||
infotext_name = S("TA3 Generator"),
|
||||
can_start = can_start,
|
||||
start_node = start_node,
|
||||
stop_node = stop_node,
|
||||
})
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local running = techage.is_running(nvm)
|
||||
local fire = has_fire(nvm)
|
||||
if running and not fire then
|
||||
State:standby(pos, nvm)
|
||||
stop_node(pos, nvm, State)
|
||||
elseif not running and fire then
|
||||
State:start(pos, nvm)
|
||||
-- start_node() is called implicit
|
||||
elseif running then
|
||||
local meta = M(pos)
|
||||
local outdir = meta:get_int("outdir")
|
||||
local tp1 = tonumber(meta:get_string("termpoint1"))
|
||||
local tp2 = tonumber(meta:get_string("termpoint2"))
|
||||
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
|
||||
local val = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
|
||||
if val > 0 then
|
||||
nvm.load = val
|
||||
end
|
||||
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
end
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
return State:is_active(nvm)
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
local function on_rightclick(pos, node, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
end
|
||||
|
||||
local function after_place_node(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local number = techage.add_node(pos, "techage:generator")
|
||||
State:node_init(pos, nvm, number)
|
||||
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
|
||||
M(pos):set_string("formspec", formspec(State, pos, nvm))
|
||||
Cable:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
Cable:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function get_generator_data(pos, outdir, tlib2)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if techage.is_running(nvm) then
|
||||
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 2}
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:generator", {
|
||||
description = S("TA3 Generator"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_hole_electric.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_generator.png^[transformFX]",
|
||||
},
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
on_timer = node_timer,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
get_generator_data = get_generator_data,
|
||||
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:generator_on", {
|
||||
description = S("TA3 Generator"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_hole_electric.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_generator4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_generator4.png^[transformFX]^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.3,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
on_receive_fields = on_receive_fields,
|
||||
on_rightclick = on_rightclick,
|
||||
on_timer = node_timer,
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
get_generator_data = get_generator_data,
|
||||
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
|
||||
|
||||
drop = "",
|
||||
paramtype2 = "facedir",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
diggable = false,
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
power.register_nodes({"techage:generator", "techage:generator_on"}, Cable, "gen", {"R"})
|
||||
|
||||
-- controlled by the turbine
|
||||
techage.register_node({"techage:generator", "techage:generator_on"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "trigger" then
|
||||
nvm.firebox_trigger = 3
|
||||
if techage.is_running(nvm) then
|
||||
return math.max((nvm.provided or PWR_PERF) / PWR_PERF, 0.02)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end,
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "delivered" then
|
||||
return math.floor((nvm.provided or 0) + 0.5)
|
||||
else
|
||||
return State:on_receive_message(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
on_beduino_receive_cmnd = function(pos, src, topic, payload)
|
||||
return State:on_beduino_receive_cmnd(pos, topic, payload)
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == 135 then -- Delivered Power
|
||||
return 0, {math.floor((nvm.provided or 0) + 0.5)}
|
||||
else
|
||||
return State:on_beduino_request_data(pos, topic, payload)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- used by power terminal
|
||||
control.register_nodes({"techage:generator", "techage:generator_on"}, {
|
||||
on_receive = function(pos, tlib2, topic, payload)
|
||||
end,
|
||||
on_request = function(pos, tlib2, topic)
|
||||
if topic == "info" then
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local meta = M(pos)
|
||||
return {
|
||||
type = S("TA3 Generator"),
|
||||
number = meta:get_string("node_number") or "",
|
||||
running = techage.is_running(nvm) or false,
|
||||
available = PWR_PERF,
|
||||
provided = nvm.provided or 0,
|
||||
termpoint = meta:get_string("termpoint"),
|
||||
}
|
||||
end
|
||||
return false
|
||||
end,
|
||||
}
|
||||
)
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:generator",
|
||||
recipe = {
|
||||
{"basic_materials:steel_bar", "dye:green", "default:wood"},
|
||||
{"", "basic_materials:gear_steel", "techage:electric_cableS"},
|
||||
{"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"},
|
||||
},
|
||||
})
|
@ -1,156 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2022 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Coal Power Station Firebox
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local P = minetest.string_to_pos
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local firebox = techage.firebox
|
||||
local fuel = techage.fuel
|
||||
local Pipe = techage.LiquidPipe
|
||||
local liquid = networks.liquid
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
local BURN_CYCLE_FACTOR = 0.5
|
||||
|
||||
local function node_timer(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local power = techage.transfer(
|
||||
{x=pos.x, y=pos.y+2, z=pos.z},
|
||||
nil, -- outdir
|
||||
"trigger", -- topic
|
||||
nil, -- payload
|
||||
nil, -- network
|
||||
{"techage:coalboiler_top"} -- nodenames
|
||||
)
|
||||
nvm.burn_cycles = (nvm.burn_cycles or 0) - math.max((power or 0.02), 0.02)
|
||||
if nvm.burn_cycles <= 0 then
|
||||
local liq_name = fuel.get_fuel(nvm)
|
||||
if liq_name then
|
||||
nvm.burn_cycles = fuel.burntime(liq_name) / CYCLE_TIME * BURN_CYCLE_FACTOR
|
||||
nvm.burn_cycles_total = nvm.burn_cycles
|
||||
else
|
||||
nvm.running = false
|
||||
firebox.set_firehole(pos, false)
|
||||
M(pos):set_string("formspec", fuel.formspec(nvm))
|
||||
return false
|
||||
end
|
||||
end
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", fuel.formspec(nvm))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function start_firebox(pos, nvm)
|
||||
if not nvm.running and fuel.has_fuel(nvm) then
|
||||
nvm.running = true
|
||||
node_timer(pos, 0)
|
||||
firebox.set_firehole(pos, true)
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("techage:oilfirebox", {
|
||||
description = S("TA3 Power Station Oil Burner"),
|
||||
inventory_image = "techage_oil_boiler_inv.png",
|
||||
tiles = {"techage_coal_boiler_mesh_top.png"},
|
||||
drawtype = "mesh",
|
||||
mesh = "techage_cylinder_12.obj",
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {-13/32, -16/32, -13/32, 13/32, 16/32, 13/32},
|
||||
},
|
||||
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_rotate = screwdriver.disallow,
|
||||
groups = {cracky=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
|
||||
on_timer = node_timer,
|
||||
can_dig = fuel.can_dig,
|
||||
on_rightclick = fuel.on_rightclick,
|
||||
on_receive_fields = fuel.on_receive_fields,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
if firebox.is_free_position(pos, placer:get_player_name()) then
|
||||
techage.add_node(pos, "techage:oilfirebox", true)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = false
|
||||
nvm.burn_cycles = 0
|
||||
nvm.liquid = {}
|
||||
nvm.liquid.amount = 0
|
||||
local meta = M(pos)
|
||||
meta:set_string("formspec", fuel.formspec(nvm))
|
||||
local inv = meta:get_inventory()
|
||||
firebox.set_firehole(pos, false)
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
firebox.set_firehole(pos, nil)
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
fuel.on_punch(pos, node, puncher, pointed_thing)
|
||||
if nvm.liquid and nvm.liquid.amount and nvm.liquid.amount > 0 then
|
||||
minetest.after(1, start_firebox, pos, nvm)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
liquid.register_nodes({"techage:oilfirebox"},
|
||||
Pipe, "tank", nil, fuel.get_liquid_table(fuel.BT_OIL, fuel.CAPACITY, start_firebox))
|
||||
|
||||
|
||||
techage.register_node({"techage:oilfirebox"}, {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "state" then
|
||||
return nvm.running and "running" or "stopped"
|
||||
elseif topic == "fuel" then
|
||||
return fuel.get_fuel_amount(nvm)
|
||||
else
|
||||
return "unsupported"
|
||||
end
|
||||
end,
|
||||
on_beduino_request_data = function(pos, src, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == 128 then
|
||||
return 0, techage.get_node_lvm(pos).name
|
||||
elseif topic == 129 then
|
||||
return 0, {nvm.running and techage.RUNNING or techage.STOPPED}
|
||||
elseif topic == 132 then
|
||||
return 0, {fuel.get_fuel_amount(nvm)}
|
||||
else
|
||||
return 2, ""
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:oilfirebox",
|
||||
recipe = {
|
||||
{'', 'techage:coalfirebox', ''},
|
||||
{'', 'techage:ta3_barrel_empty', ''},
|
||||
{'', '', ''},
|
||||
},
|
||||
})
|
@ -1,182 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA3 Power Station Turbine
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
local Pipe = techage.SteamPipe
|
||||
|
||||
local function transfer_cooler(pos, topic, payload)
|
||||
return techage.transfer(pos, 6, topic, payload, Pipe,
|
||||
{"techage:cooler", "techage:cooler_on"})
|
||||
end
|
||||
|
||||
local function transfer_generator(pos, topic, payload)
|
||||
return techage.transfer(pos, "R", topic, payload, nil,
|
||||
{"techage:generator", "techage:generator_on"})
|
||||
end
|
||||
|
||||
local function swap_node(pos, name)
|
||||
local node = techage.get_node_lvm(pos)
|
||||
if node.name == name then
|
||||
return
|
||||
end
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
local function play_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if not mem.handle or mem.handle == -1 then
|
||||
mem.handle = minetest.sound_play("techage_turbine", {
|
||||
pos = pos,
|
||||
gain = 1,
|
||||
max_hear_distance = 15,
|
||||
loop = true})
|
||||
if mem.handle == -1 then
|
||||
minetest.after(1, play_sound, pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_sound(pos)
|
||||
local mem = techage.get_mem(pos)
|
||||
if mem.handle then
|
||||
minetest.sound_stop(mem.handle)
|
||||
mem.handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function after_place_node(pos)
|
||||
Pipe:after_place_node(pos)
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode)
|
||||
stop_sound(pos)
|
||||
Pipe:after_dig_node(pos)
|
||||
techage.del_mem(pos)
|
||||
end
|
||||
|
||||
local function tubelib2_on_update2(pos, outdir, tlib2, node)
|
||||
swap_node(pos, "techage:turbine")
|
||||
stop_sound(pos)
|
||||
end
|
||||
|
||||
minetest.register_node("techage:turbine", {
|
||||
description = S("TA3 Turbine"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png^[transformFX",
|
||||
"techage_filling_ta3.png^techage_appl_turbine.png^techage_frame_ta3.png",
|
||||
},
|
||||
|
||||
after_place_node = after_place_node,
|
||||
after_dig_node = after_dig_node,
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, crumbly=2, choppy=2},
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_node("techage:turbine_on", {
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_appl_open.png^techage_frame_ta3.png",
|
||||
"techage_filling_ta3.png^techage_frame_ta3.png^techage_steam_hole.png",
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_turbine4.png^techage_frame4_ta3.png^[transformFX",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "techage_filling4_ta3.png^techage_appl_turbine4.png^techage_frame4_ta3.png",
|
||||
backface_culling = false,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 0.4,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
tubelib2_on_update2 = tubelib2_on_update2,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
diggable = false,
|
||||
on_rotate = screwdriver.disallow,
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
Pipe:add_secondary_node_names({"techage:turbine", "techage:turbine_on"})
|
||||
|
||||
techage.register_node({"techage:turbine", "techage:turbine_on"}, {
|
||||
on_transfer = function(pos, in_dir, topic, payload)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
if topic == "trigger" then -- used by boiler
|
||||
if not transfer_cooler(pos, topic, payload) then
|
||||
return 0
|
||||
end
|
||||
local power = transfer_generator(pos, topic, payload)
|
||||
if not power or power <= 0 and nvm.running then
|
||||
swap_node(pos, "techage:turbine")
|
||||
stop_sound(pos)
|
||||
nvm.running = false
|
||||
return 0
|
||||
end
|
||||
return power
|
||||
elseif topic == "start" then -- used by generator
|
||||
swap_node(pos, "techage:turbine_on")
|
||||
play_sound(pos)
|
||||
nvm.running = true
|
||||
return true
|
||||
elseif topic == "stop" then -- used by generator
|
||||
swap_node(pos, "techage:turbine")
|
||||
stop_sound(pos)
|
||||
nvm.running = false
|
||||
return true
|
||||
end
|
||||
end,
|
||||
on_node_load = function(pos, node)
|
||||
if node.name == "techage:turbine_on" then
|
||||
play_sound(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:turbine",
|
||||
recipe = {
|
||||
{"basic_materials:steel_bar", "techage:steam_pipeS", "default:wood"},
|
||||
{"techage:steam_pipeS", "basic_materials:gear_steel", ""},
|
||||
{"default:wood", "techage:iron_ingot", "basic_materials:steel_bar"},
|
||||
},
|
||||
})
|
@ -1,89 +0,0 @@
|
||||
--[[
|
||||
|
||||
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
|
||||
{
|
||||
name = "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,
|
||||
},
|
||||
},
|
||||
{
|
||||
name = "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",
|
||||
},
|
||||
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', ''},
|
||||
},
|
||||
})
|
@ -1,448 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 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 IMPROBABILITY = 40 -- every 40 min
|
||||
-- one point per 40 min: check every 20 s => factor = 40 * 3 = 120
|
||||
IMPROBABILITY = (minetest.settings:get("techage_expoint_rate_in_min") or 40) * 3
|
||||
|
||||
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(IMPROBABILITY) == 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, task)
|
||||
end
|
||||
|
||||
-- Call on_cyclic_check of all magents so that the magnets don't need a FLB.
|
||||
local function magnets_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
|
||||
|
||||
-- Turn off all magnets so that they don't consume power
|
||||
local function magnets_turn_off(pos, nvm)
|
||||
local ndef = minetest.registered_nodes["techage:ta4_magnet"]
|
||||
for idx,pos2 in ipairs(nvm.magnet_positions or {}) do
|
||||
ndef.on_turn_off(pos2)
|
||||
end
|
||||
end
|
||||
|
||||
local function cable_inlets_turn_on_off(pos, on)
|
||||
local turn_on_off = function(pos, param2, item)
|
||||
local pos2 = getpos(pos, param2, item.route, item.yoffs)
|
||||
local node2 = minetest.get_node(pos2)
|
||||
if item.name == node2.name then
|
||||
local nvm = techage.get_nvm(pos2)
|
||||
techage.power_inlet_turn_on_off(pos2, nvm, on)
|
||||
end
|
||||
end
|
||||
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
turn_on_off(pos, param2, Schedule[2])
|
||||
turn_on_off(pos, param2, Schedule[3])
|
||||
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",
|
||||
},
|
||||
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 nvm.running then
|
||||
if not magnets_on_cyclic_check(pos, nvm) then
|
||||
techage.del_laser(pos)
|
||||
terminal_message(pos, "Detector stopped.")
|
||||
magnets_turn_off(pos, nvm)
|
||||
cable_inlets_turn_on_off(pos, false)
|
||||
nvm.running = false
|
||||
nvm.magnet_positions = nil
|
||||
else
|
||||
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)
|
||||
magnets_turn_off(pos, nvm)
|
||||
cable_inlets_turn_on_off(pos, false)
|
||||
nvm.running = false
|
||||
nvm.magnet_positions = nil
|
||||
terminal_message(pos, "Detector stopped.")
|
||||
end
|
||||
if nvm.running then
|
||||
play_sound(pos)
|
||||
end
|
||||
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")
|
||||
cable_inlets_turn_on_off(pos, true)
|
||||
|
||||
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
|
||||
cable_inlets_turn_on_off(pos, 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
|
||||
cable_inlets_turn_on_off(pos, false)
|
||||
return
|
||||
end
|
||||
else
|
||||
techage.send_single(own_num, term_num, "append", "defect!!!")
|
||||
nvm.magnet_positions = nil
|
||||
nvm.locked = false
|
||||
cable_inlets_turn_on_off(pos, 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 starting...")
|
||||
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
|
||||
magnets_turn_off(pos, nvm)
|
||||
cable_inlets_turn_on_off(pos, false)
|
||||
nvm.magnet_positions = nil
|
||||
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'},
|
||||
},
|
||||
})
|
@ -1,375 +0,0 @@
|
||||
--[[
|
||||
|
||||
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",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
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)
|
||||
if nvm.running then
|
||||
nvm.consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
|
||||
else
|
||||
nvm.consumed = 0
|
||||
end
|
||||
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
|
||||
|
||||
-- Used by the detector to turn on/off the node
|
||||
function techage.power_inlet_turn_on_off(pos, nvm, on)
|
||||
nvm.running = on
|
||||
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', ''},
|
||||
{'', '', ''},
|
||||
},
|
||||
})
|
@ -1,333 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2023 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
|
||||
|
||||
local function is_junction(pos, side)
|
||||
local node = techage.get_node_lvm(techage.get_pos(pos, side))
|
||||
return node and techage.string_compare(node.name, "techage:ta3_junction")
|
||||
end
|
||||
|
||||
-- Turn the magnet to the right direction
|
||||
local function handle_legacy_magnet(pos)
|
||||
if M(pos):get_string("version") ~= "V2" then
|
||||
if is_junction(pos, "B") and not is_junction(pos, "F") then
|
||||
local node = techage.get_node_lvm(pos)
|
||||
node.param2 = (node.param2 + 2) % 4
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
M(pos):set_string("version", "V2")
|
||||
end
|
||||
|
||||
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",
|
||||
},
|
||||
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_collider_magnet_appl.png^techage_appl_hole_pipe.png^techage_collider_magnet_sign.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_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",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
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")
|
||||
M(pos):set_string("version", "V2")
|
||||
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
|
||||
nvm.running = nil
|
||||
return -1
|
||||
elseif nvm.liquid.amount == CAPACITY and
|
||||
nvm.liquid.name == "techage:isobutane" and
|
||||
nvm.consumed == PWR_NEEDED then
|
||||
nvm.running = true
|
||||
return 0
|
||||
end
|
||||
nvm.running = nil
|
||||
return -2
|
||||
end,
|
||||
|
||||
on_turn_off = function(pos)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
nvm.running = nil
|
||||
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"}, {
|
||||
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
|
||||
handle_legacy_magnet(pos)
|
||||
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,
|
||||
})
|
@ -1,130 +0,0 @@
|
||||
--[[
|
||||
|
||||
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', ''},
|
||||
},
|
||||
})
|
@ -1,208 +0,0 @@
|
||||
--[[
|
||||
|
||||
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",
|
||||
},
|
||||
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'},
|
||||
},
|
||||
})
|
@ -1,175 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
Copyright (C) 2020 Thomas S.
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
Electricity powered battery for Digtron
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local S = techage.S
|
||||
|
||||
-- Consumer Related Data
|
||||
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
|
||||
|
||||
local STANDBY_TICKS = 3
|
||||
local COUNTDOWN_TICKS = 4
|
||||
local CYCLE_TIME = 4
|
||||
local INV_SIZE = 4
|
||||
local FUEL = "default:coal_lump"
|
||||
local FUEL_STACK_MAX = ItemStack(FUEL):get_stack_max()
|
||||
local TOTAL_MAX = INV_SIZE * FUEL_STACK_MAX
|
||||
|
||||
local function count_coal(metadata)
|
||||
local total = 0
|
||||
for _,stack in pairs(metadata.inventory.fuel or {}) do
|
||||
total = total + stack:get_count()
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function formspec(self, pos, nvm)
|
||||
local meta = M(pos):to_table()
|
||||
local total = 0
|
||||
if meta.inventory then
|
||||
total = count_coal(meta)
|
||||
end
|
||||
return "size[5,4]"..
|
||||
default.gui_bg..
|
||||
default.gui_bg_img..
|
||||
default.gui_slots..
|
||||
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
|
||||
"label[1,-0.1;"..minetest.colorize("#000000", S("Digtron Battery")).."]"..
|
||||
techage.formspec_label_bar(pos, 0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
|
||||
"image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
|
||||
"tooltip[2.6,2;1,1;"..self:get_state_tooltip(nvm).."]"..
|
||||
"image[3.75,2;1,1;"..techage.get_power_image(pos, nvm).."]"
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
return 0
|
||||
end
|
||||
|
||||
local function produce_coal(pos, crd, nvm, inv)
|
||||
local stack = ItemStack(FUEL)
|
||||
if inv:room_for_item("fuel", stack) then
|
||||
inv:add_item("fuel", stack)
|
||||
crd.State:keep_running(pos, nvm, COUNTDOWN_TICKS)
|
||||
else
|
||||
crd.State:idle(pos, nvm)
|
||||
end
|
||||
end
|
||||
|
||||
local function keep_running(pos, elapsed)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
local crd = CRD(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
produce_coal(pos, crd, nvm, inv)
|
||||
|
||||
if techage.is_activeformspec(pos) then
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end
|
||||
end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local nvm = techage.get_nvm(pos)
|
||||
CRD(pos).State:state_button_event(pos, nvm, fields)
|
||||
end
|
||||
|
||||
|
||||
local tiles = {}
|
||||
-- '#' will be replaced by the stage number
|
||||
-- '{power}' will be replaced by the power PNG
|
||||
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"digtron_plate.png^digtron_core.png",
|
||||
"digtron_plate.png^digtron_core.png",
|
||||
"digtron_plate.png^digtron_battery.png",
|
||||
"digtron_plate.png^digtron_battery.png",
|
||||
"digtron_plate.png^digtron_battery.png",
|
||||
"digtron_plate.png^digtron_battery.png",
|
||||
}
|
||||
|
||||
local tubing = {
|
||||
on_recv_message = function(pos, src, topic, payload)
|
||||
return CRD(pos).State:on_receive_message(pos, topic, payload)
|
||||
end,
|
||||
}
|
||||
|
||||
local node_name_ta2, node_name_ta3, node_name_ta4 =
|
||||
techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles, pas = tiles }, {
|
||||
drawtype = "normal",
|
||||
paramtype = "light",
|
||||
cycle_time = CYCLE_TIME,
|
||||
standby_ticks = STANDBY_TICKS,
|
||||
formspec = formspec,
|
||||
tubing = tubing,
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('fuel', INV_SIZE)
|
||||
if itemstack then
|
||||
local stack_meta = itemstack:get_meta()
|
||||
if stack_meta then
|
||||
local coal_amount = techage.in_range(stack_meta:get_int("coal"), 0, TOTAL_MAX)
|
||||
while coal_amount > 0 do
|
||||
local amount = math.min(coal_amount, FUEL_STACK_MAX)
|
||||
inv:add_item("fuel", ItemStack(FUEL.." "..amount))
|
||||
coal_amount = coal_amount - amount;
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
preserve_metadata = function(pos, oldnode, oldmetadata, drops)
|
||||
local metadata = M(pos):to_table()
|
||||
if metadata.inventory then
|
||||
local total = count_coal(metadata)
|
||||
local meta = drops[1]:get_meta()
|
||||
meta:set_int("coal", total)
|
||||
local text = S("Digtron Battery").." ("..math.floor(total/TOTAL_MAX * 100).." %)"
|
||||
meta:set_string("description", text)
|
||||
end
|
||||
end,
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
techage.set_activeformspec(pos, clicker)
|
||||
local nvm = techage.get_nvm(pos)
|
||||
M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm))
|
||||
end,
|
||||
node_timer = keep_running,
|
||||
on_receive_fields = on_receive_fields,
|
||||
allow_metadata_inventory_put = allow_metadata_inventory_put,
|
||||
allow_metadata_inventory_move = allow_metadata_inventory_move,
|
||||
allow_metadata_inventory_take = allow_metadata_inventory_take,
|
||||
groups = {choppy=2, cracky=2, crumbly=2, digtron=5},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
power_consumption = {0,25,25,25},
|
||||
power_sides = {L=1, R=1, U=1, D=1, F=1, B=1},
|
||||
}, {false, false, true, false})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name_ta3,
|
||||
recipe = {
|
||||
{"group:wood", "default:copper_ingot", "group:wood"},
|
||||
{"techage:electric_cableS", "default:tin_ingot", "digtron:digtron_core"},
|
||||
{"group:wood", "default:copper_ingot", "group:wood"},
|
||||
},
|
||||
})
|
@ -1,279 +0,0 @@
|
||||
--[[
|
||||
|
||||
]]--
|
||||
|
||||
local S = techage.S
|
||||
local M = minetest.get_meta
|
||||
local MP = minetest.get_modpath("techage")
|
||||
|
||||
local settings = {
|
||||
symbol_item = "techage:construction_board_EN",
|
||||
}
|
||||
|
||||
doclib.create_manual("techage", "DE", settings)
|
||||
doclib.create_manual("techage", "EN", settings)
|
||||
doclib.create_manual("techage", "pt-BR", settings)
|
||||
doclib.create_manual("techage", "RU", settings)
|
||||
|
||||
local content
|
||||
content = dofile(MP.."/doc/manual_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
content = dofile(MP.."/doc/manual_ta1_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
content = dofile(MP.."/doc/manual_ta2_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
content = dofile(MP.."/doc/manual_ta3_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
content = dofile(MP.."/doc/manual_ta4_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
content = dofile(MP.."/doc/manual_ta5_DE.lua")
|
||||
doclib.add_to_manual("techage", "DE", content)
|
||||
|
||||
content = dofile(MP.."/doc/manual_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
content = dofile(MP.."/doc/manual_ta1_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
content = dofile(MP.."/doc/manual_ta2_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
content = dofile(MP.."/doc/manual_ta3_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
content = dofile(MP.."/doc/manual_ta4_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
content = dofile(MP.."/doc/manual_ta5_EN.lua")
|
||||
doclib.add_to_manual("techage", "EN", content)
|
||||
|
||||
content = dofile(MP.."/doc/manual_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_ta1_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_ta2_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_ta3_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_ta4_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_ta5_RU.lua")
|
||||
doclib.add_to_manual("techage", "RU", content)
|
||||
content = dofile(MP.."/doc/manual_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
content = dofile(MP.."/doc/manual_ta1_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
content = dofile(MP.."/doc/manual_ta2_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
content = dofile(MP.."/doc/manual_ta3_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
content = dofile(MP.."/doc/manual_ta4_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
content = dofile(MP.."/doc/manual_ta5_pt-BR.lua")
|
||||
doclib.add_to_manual("techage", "pt-BR", content)
|
||||
|
||||
local board_box = {
|
||||
type = "wallmounted",
|
||||
wall_side = {-16/32, -11/32, -16/32, -15/32, 6/16, 8/16},
|
||||
}
|
||||
|
||||
minetest.register_node("techage:construction_board", {
|
||||
description = "TA Konstruktionsplan (DE)",
|
||||
inventory_image = 'techage_constr_plan_inv_de.png',
|
||||
tiles = {"techage_constr_plan_de.png"},
|
||||
drawtype = "nodebox",
|
||||
node_box = board_box,
|
||||
selection_box = board_box,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
M(pos):set_string("infotext", "TA Konstruktionsplan (DE)")
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "DE"))
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local player_name = player:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
return
|
||||
end
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "DE", fields))
|
||||
end,
|
||||
|
||||
paramtype2 = "wallmounted",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:construction_board",
|
||||
recipe = {
|
||||
{"default:stick", "default:stick", "default:stick"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("techage:construction_board_EN", {
|
||||
description = "TA Construction Board (EN)",
|
||||
inventory_image = 'techage_constr_plan_inv.png',
|
||||
tiles = {"techage_constr_plan.png"},
|
||||
drawtype = "nodebox",
|
||||
node_box = board_box,
|
||||
selection_box = board_box,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
M(pos):set_string("infotext", "TA Construction Board (EN)")
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "EN"))
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local player_name = player:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
return
|
||||
end
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "EN", fields))
|
||||
end,
|
||||
|
||||
paramtype2 = "wallmounted",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:construction_board_EN",
|
||||
recipe = {
|
||||
{"default:stick", "default:paper", "default:stick"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("techage:construction_board_RU", {
|
||||
description = "TA Construction Board (RU)",
|
||||
inventory_image = 'techage_constr_plan_inv_ru.png',
|
||||
tiles = {"techage_constr_plan_ru.png"},
|
||||
drawtype = "nodebox",
|
||||
node_box = board_box,
|
||||
selection_box = board_box,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
M(pos):set_string("infotext", "План строительства ТА (RU)")
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "RU"))
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local player_name = player:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
return
|
||||
end
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "RU", fields))
|
||||
end,
|
||||
|
||||
paramtype2 = "wallmounted",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:construction_board_RU",
|
||||
recipe = {
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_node("techage:construction_board_pt_BR", {
|
||||
description = "TA Placa de construção (pt-BR)",
|
||||
inventory_image = 'techage_constr_plan_inv_br.png',
|
||||
tiles = {"techage_constr_plan_br.png"},
|
||||
drawtype = "nodebox",
|
||||
node_box = board_box,
|
||||
selection_box = board_box,
|
||||
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
M(pos):set_string("infotext", "TA Placa de construção (pt-BR)")
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "pt-BR"))
|
||||
end,
|
||||
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local player_name = player:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
return
|
||||
end
|
||||
M(pos):set_string("formspec", doclib.formspec(pos, "techage", "pt-BR", fields))
|
||||
end,
|
||||
|
||||
paramtype2 = "wallmounted",
|
||||
paramtype = "light",
|
||||
use_texture_alpha = techage.CLIP,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "techage:construction_board_pt_BR",
|
||||
recipe = {
|
||||
{"default:stick", "default:stick", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
{"default:paper", "default:paper", "default:paper"},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:construction_board_EN",
|
||||
recipe = {"techage:construction_board"},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:construction_board_RU",
|
||||
recipe = { "techage:construction_board_EN" },
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:construction_board_pt_BR",
|
||||
recipe = {"techage:construction_board_RU"},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "techage:construction_board",
|
||||
recipe = {"techage:construction_board_pt_BR"},
|
||||
})
|
||||
|
||||
--
|
||||
-- Legacy API functions
|
||||
--
|
||||
function techage.add_to_manual(language, titles, texts, items, plans)
|
||||
local content = {titles = titles, texts = texts, images = items or {}, plans = plans or {}}
|
||||
doclib.add_to_manual("techage", language, content)
|
||||
end
|
||||
|
||||
function techage.add_manual_items(table_with_items)
|
||||
for name, image in pairs(table_with_items) do
|
||||
doclib.add_manual_image("techage", "EN", name, image)
|
||||
doclib.add_manual_image("techage", "DE", name, image)
|
||||
doclib.add_manual_image("techage", "pt-BR", name, image)
|
||||
doclib.add_manual_image("techage", "RU", name, image)
|
||||
end
|
||||
end
|
||||
|
||||
function techage.add_manual_plans(table_with_plans)
|
||||
for name, plan in pairs(table_with_plans) do
|
||||
doclib.add_manual_plan("techage", "EN", name, plan)
|
||||
doclib.add_manual_plan("techage", "DE", name, plan)
|
||||
doclib.add_manual_plan("techage", "RU", name, plan)
|
||||
doclib.add_manual_plan("techage", "pt-BR", name, plan)
|
||||
end
|
||||
end
|
@ -1,234 +0,0 @@
|
||||
--[[
|
||||
|
||||
TechAge
|
||||
=======
|
||||
|
||||
Copyright (C) 2019 Joachim Stolberg
|
||||
|
||||
AGPL v3
|
||||
See LICENSE.txt for more information
|
||||
|
||||
TA Items Table
|
||||
|
||||
]]--
|
||||
|
||||
local items = {
|
||||
techage_ta1 = "techage_ta1.png",
|
||||
iron = "techage:iron_ingot",
|
||||
charcoal = "techage:charcoal",
|
||||
lighter = "techage:lighter",
|
||||
ta1_gravelsieve = "techage:sieve3",
|
||||
hammer = "techage:hammer_bronze",
|
||||
meridium = "techage:meridium_ingot",
|
||||
baborium = "techage:stone_with_baborium",
|
||||
bauxite = "techage:bauxite_stone",
|
||||
usmium = "techage:usmium_nuggets",
|
||||
basalt = "techage:basalt_stone",
|
||||
oil = "techage:oil_source",
|
||||
ta1_hopper = "techage:hopper_ta1",
|
||||
wlanchip = "techage:ta4_wlanchip",
|
||||
tube = "techage:tubeS",
|
||||
concentrator = "techage:concentrator27",
|
||||
ta1_sluice = "techage:ta1_sluice_closed",
|
||||
ta1_sluice_handle = "techage:ta1_sluice_handle_closed",
|
||||
ta1_board1 = "techage:ta1_board1_apple",
|
||||
ta1_board2 = "techage:ta1_board2_apple",
|
||||
----------------
|
||||
techage_ta2 = "techage_ta2.png",
|
||||
ta2_firebox = "techage:firebox",
|
||||
ta2_boiler = "techage:boiler2",
|
||||
ta2_cylinder = "techage:cylinder",
|
||||
ta2_flywheel = "techage:flywheel",
|
||||
ta2_steampipe = "techage:steam_pipeS",
|
||||
ta2_distributor = "techage:ta2_distributor_pas",
|
||||
ta2_pusher = "techage:ta2_pusher_pas",
|
||||
ta2_gravelrinser = "techage:ta2_rinser_pas",
|
||||
ta2_grinder = "techage:ta2_grinder_pas",
|
||||
ta2_quarry = "techage:ta2_quarry_pas",
|
||||
ta2_autocrafter = "techage:ta2_autocrafter_pas",
|
||||
ta2_electronicfab = "techage:ta2_electronic_fab_pas",
|
||||
ta2_gravelsieve = "techage:ta2_gravelsieve_pas",
|
||||
ta2_liquidsampler = "techage:ta2_liquidsampler_pas",
|
||||
ta2_rinser = "techage:ta2_rinser_pas",
|
||||
ta2_chest = "techage:chest_ta2",
|
||||
ta2_forceload = "techage:forceload",
|
||||
ta2_driveaxle = "techage:axle",
|
||||
ta2_generator = "techage:ta2_generator_off",
|
||||
ta2_winch = "techage:ta2_winch",
|
||||
ta2_weight_chest = "techage:ta2_weight_chest",
|
||||
---------------------
|
||||
techage_ta3 = "techage_ta3.png",
|
||||
techage_ta31 = "techage_ta3b.png",
|
||||
ta3_firebox = "techage:coalfirebox",
|
||||
ta3_oilbox = "techage:oilfirebox",
|
||||
ta3_boiler = "techage:coalboiler_top",
|
||||
ta3_turbine = "techage:turbine",
|
||||
ta3_generator = "techage:generator",
|
||||
ta3_cooler = "techage:cooler",
|
||||
ta3_distributor = "techage:ta3_distributor_pas",
|
||||
ta3_pusher = "techage:ta3_pusher_pas",
|
||||
ta3_gravelrinser = "techage:ta3_rinser_pas",
|
||||
ta3_grinder = "techage:ta3_grinder_pas",
|
||||
ta3_quarry = "techage:ta3_quarry_pas",
|
||||
ta3_autocrafter = "techage:ta3_autocrafter_pas",
|
||||
ta3_electronicfab = "techage:ta3_electronic_fab_pas",
|
||||
ta3_gravelsieve = "techage:ta3_gravelsieve_pas",
|
||||
ta3_liquidsampler = "techage:ta3_liquidsampler_pas",
|
||||
ta3_powercable = "techage:electric_cableS",
|
||||
ta3_powerline = "techage:power_lineS",
|
||||
ta3_powerswitch = "techage:powerswitch",
|
||||
ta3_powerswitchsmall = "techage:powerswitchsmall",
|
||||
ta3_powerjunction = "techage:electric_junction0",
|
||||
ta3_powerpole = "techage:power_pole3",
|
||||
ta3_powerpole2 = "techage:power_pole2",
|
||||
ta3_powerpole4 = "techage:power_pole",
|
||||
ta3_powerswitchbox = "techage:powerswitch_box",
|
||||
ta3_powerterminal = "techage:ta3_power_terminal",
|
||||
ta3_trowel = "techage:trowel",
|
||||
ta3_screwdriver = "techage:screwdriver",
|
||||
ta3_tinygenerator = "techage:tiny_generator",
|
||||
ta3_akkublock = "techage:ta3_akku",
|
||||
ta3_furnace = "techage:ta3_furnace_pas",
|
||||
ta3_furnacefirebox = "techage:furnace_firebox",
|
||||
ta3_booster = "techage:ta3_booster",
|
||||
ta3_oilexplorer = "techage:oilexplorer",
|
||||
ta3_drillbox = "techage:ta3_drillbox_pas",
|
||||
ta3_pumpjack = "techage:ta3_pumpjack_pas",
|
||||
ta3_drillbit = "techage:oil_drillbit",
|
||||
ta3_end_wrench = "techage:end_wrench",
|
||||
ta3_tank = "techage:ta3_tank",
|
||||
ta3_pump = "techage:t3_pump",
|
||||
oiltank = "techage:oiltank",
|
||||
reboiler = "techage:ta3_reboiler",
|
||||
ta3_filler = "techage:filler",
|
||||
tank_cart = "techage:tank_cart",
|
||||
chest_cart = "techage:chest_cart",
|
||||
----------------------------
|
||||
ta3_button = "techage:ta3_button_off",
|
||||
ta3_cartdetector = "techage:ta3_cartdetector_off",
|
||||
ta3_detector = "techage:ta3_detector_off",
|
||||
ta3_logic = "techage:ta3_logic",
|
||||
ta3_nodedetector = "techage:ta3_nodedetector_off",
|
||||
ta3_playerdetector = "techage:ta3_playerdetector_off",
|
||||
ta3_lightdetector = "techage:ta3_lightdetector_off",
|
||||
ta3_repeater = "techage:ta3_repeater",
|
||||
ta3_sequencer = "techage:ta3_sequencer",
|
||||
ta3_timer = "techage:ta3_timer",
|
||||
ta3_terminal = "techage:terminal2",
|
||||
ta3_colorlamp = "techage:color_lamp_off",
|
||||
ta3_doorblock = "techage:doorblock20",
|
||||
ta3_soundblock = "techage:ta3_soundblock",
|
||||
ta3_programmer = "techage:programmer",
|
||||
ta3_doorcontroller = "techage:ta3_doorcontroller",
|
||||
ta3_drill_pipe_wrench = "techage:ta3_drill_pipe_wrench",
|
||||
ta3_pipe = "techage:ta3_pipeS",
|
||||
ta3_pipe_wall_entry = "techage:ta3_pipe_wall_entry",
|
||||
ta3_mesecons_converter = "techage:ta3_mesecons_converter",
|
||||
ta3_valve = "techage:ta3_valve_closed",
|
||||
ta3_motor = "techage:ta3_motor_off",
|
||||
ta3_injector = "techage:ta3_injector_pas",
|
||||
ta3_command_converter = "techage:ta3_command_converter_off",
|
||||
ta3_flipflop = "techage:ta3_flipflop_off",
|
||||
----------------------------
|
||||
techage_ta4 = "techage_ta4.png",
|
||||
techage_ta4c = "techage_ta4c.png",
|
||||
ta4_windturbine = "techage:ta4_wind_turbine",
|
||||
ta4_pillar = "techage:pillar",
|
||||
ta4_blinklamp = "techage:rotor_signal_lamp_off",
|
||||
ta4_nacelle = "techage:ta4_wind_turbine_nacelle",
|
||||
ta4_minicell = "techage:ta4_solar_minicell",
|
||||
ta4_pipe = "techage:ta4_pipeS",
|
||||
ta4_tube = "techage:ta4_tubeS",
|
||||
ta4_junctionpipe = "techage:ta4_junctionpipe25",
|
||||
ta4_pipeinlet = "techage:ta4_pipe_inlet",
|
||||
ta4_turbine = "techage:ta4_turbine",
|
||||
ta4_generator = "techage:ta4_generator",
|
||||
ta4_heatexchanger = "techage:heatexchanger3",
|
||||
ta4_powercable = "techage:ta4_power_cableS",
|
||||
ta4_powerbox = "techage:ta4_power_box",
|
||||
ta4_solarmodule = "techage:ta4_solar_module",
|
||||
ta4_solarcarrier = "techage:ta4_solar_carrier",
|
||||
ta4_solar_inverter = "techage:ta4_solar_inverter",
|
||||
techage_ta4_solar = "techage_ta4_solar.png",
|
||||
ta4_hydrogen = "techage_hydrogen_inv.png",
|
||||
ta4_electrolyzer = "techage:ta4_electrolyzer",
|
||||
ta4_fuelcell = "techage:ta4_fuelcell",
|
||||
ta4_reactor = "techage:ta4_reactor",
|
||||
ta4_tank = "techage:ta4_tank",
|
||||
ta4_pump = "techage:t4_pump",
|
||||
ta4_doser = "techage:ta4_doser",
|
||||
ta4_silo = "techage:ta4_silo",
|
||||
ta4_fillerpipe = "techage:ta4_reactor_fillerpipe",
|
||||
ta4_reactorstand = "techage:ta4_reactor_stand",
|
||||
ta4_reactorbase = "techage:ta4_reactor_base",
|
||||
ta4_furnaceheater = "techage:furnace_heater",
|
||||
ta4_waterpump = "techage:t4_waterpump",
|
||||
ta4_icta_controller = "techage:ta4_icta_controller",
|
||||
ta4_battery = "techage:ta4_battery",
|
||||
ta4_display = "techage:ta4_display",
|
||||
ta4_displayXL = "techage:ta4_displayXL",
|
||||
ta4_signaltower = "techage:ta4_signaltower",
|
||||
ta4_lua_controller = "techage:ta4_lua_controller",
|
||||
ta4_lua_server = "techage:ta4_server",
|
||||
ta4_sensor_chest = "techage:ta4_sensor_chest",
|
||||
ta4_terminal = "techage:ta4_terminal",
|
||||
ta4_button = "techage:ta4_button_off",
|
||||
ta4_playerdetector = "techage:ta4_playerdetector_off",
|
||||
ta4_collector = "techage:ta4_collector",
|
||||
ta4_pusher = "techage:ta4_pusher_pas",
|
||||
ta4_distributor = "techage:ta4_distributor_pas",
|
||||
ta4_high_performance_distributor = "techage:ta4_high_performance_distributor_pas",
|
||||
ta4_gravelsieve = "techage:ta4_gravelsieve_pas",
|
||||
ta4_grinder = "techage:ta4_grinder_pas",
|
||||
ta4_detector = "techage:ta4_detector_off",
|
||||
ta4_chest = "techage:chest_ta4",
|
||||
ta4_8x2000_chest = "techage:ta4_chest",
|
||||
ta4_growlight = "techage:growlight_on",
|
||||
ta4_streetlamp = "techage_ta4_streetlamp.png",
|
||||
ta4_industriallamp = "techage:industriallamp4_off",
|
||||
ta4_quarry = "techage:ta4_quarry_pas",
|
||||
ta4_electronicfab = "techage:ta4_electronic_fab_pas",
|
||||
ta4_injector = "techage:ta4_injector_pas",
|
||||
ta4_liquid_filter = "techage_ta4_filter.png",
|
||||
ta4_recycler = "techage:ta4_recycler_pas",
|
||||
ta4_waterinlet = "techage:ta4_waterinlet",
|
||||
ta4_laser = "techage:ta4_laser_emitter",
|
||||
ta4_concentrator = "techage:ta4_concentrator27",
|
||||
ta4_electricmeter = "techage:ta4_electricmeter",
|
||||
ta4_transformer = "techage:ta4_transformer",
|
||||
power_reduction = "techage_power_reduction.png",
|
||||
ta4_button_2x = "techage:ta4_button_2x",
|
||||
ta4_button_4x = "techage:ta4_button_4x",
|
||||
ta4_sequencer = "techage:ta4_sequencer",
|
||||
ta4_movecontroller = "techage:ta4_movecontroller",
|
||||
ta4_turncontroller = "techage:ta4_turncontroller",
|
||||
ta4_signallamp_2x = "techage:ta4_signallamp_2x",
|
||||
ta4_signallamp_4x = "techage:ta4_signallamp_4x",
|
||||
ta4_terminal = "techage:terminal3",
|
||||
ta4_autocrafter = "techage:ta4_autocrafter_pas",
|
||||
ta4_recipeblock = "techage:ta4_recipeblock",
|
||||
ta4_chargedetector = "techage:ta4_chargedetector_off",
|
||||
ta4_gaze_sensor = "techage:ta4_gaze_sensor_off",
|
||||
ta4_nodedetector = "techage:ta4_nodedetector_off",
|
||||
----------------------------
|
||||
techage_ta5 = "techage:ta5_fr_nucleus",
|
||||
ta5_flycontroller = "techage:ta5_flycontroller",
|
||||
ta5_aichip = "techage:ta5_aichip",
|
||||
ta5_aichip2 = "techage:ta5_aichip2",
|
||||
ta5_tele_pipe = "techage:ta5_tele_pipe",
|
||||
ta5_tele_tube = "techage:ta5_tele_tube",
|
||||
ta5_chest = "techage:ta5_hl_chest",
|
||||
ta5_tank = "techage:ta5_hl_tank",
|
||||
ta5_magnet = "techage:ta5_magnet1",
|
||||
ta5_pump = "techage:ta5_pump",
|
||||
ta5_fr_shell = "techage:ta5_fr_shell",
|
||||
ta5_fr_nucleus = "techage:ta5_fr_nucleus",
|
||||
ta5_fr_controller = "techage:ta5_fr_controller_pas",
|
||||
}
|
||||
|
||||
for name, image in pairs(items) do
|
||||
doclib.add_manual_image("techage", "DE", name, image)
|
||||
doclib.add_manual_image("techage", "EN", name, image)
|
||||
doclib.add_manual_image("techage", "pt-BR", name, image)
|
||||
doclib.add_manual_image("techage", "RU", name, image)
|
||||
end
|
@ -1,132 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,Tech Age Mod",
|
||||
"2,Hinweise",
|
||||
"2,Änderungen ab Version 1.0",
|
||||
"3,Tipps zur Umstellung",
|
||||
"2,Erze und Mineralien",
|
||||
"3,Meridium",
|
||||
"3,Usmium",
|
||||
"3,Baborium",
|
||||
"3,Erdöl",
|
||||
"3,Bauxit",
|
||||
"3,Basalt",
|
||||
},
|
||||
texts = {
|
||||
"Tech Age ist eine Technik-Mod mit 5 Entwicklungsstufen:\n"..
|
||||
"\n"..
|
||||
"TA1: Eisenzeitalter (Iron Age)\n"..
|
||||
"Benutze Werkzeuge und Hilfsmittel wie Köhler\\, Kohlebrenner\\, Kiessieb\\, Hammer\\, Hopper um notwendige Erze und Metalle zu schürfen und zu verarbeiten.\n"..
|
||||
"\n"..
|
||||
"TA2: Dampfzeitalter (Steam Age)\n"..
|
||||
"Baue eine Dampfmaschine mit Antriebsachsen und betreibe damit deine ersten Maschinen zur Verarbeitung von Erzen.\n"..
|
||||
"\n"..
|
||||
"TA3: Ölzeitalter (Oil Age)\n"..
|
||||
"Suche und fördere Öl\\, baute Schienenwege zur Ölbeförderung. Ein Kraftwerk liefert den notwendigen Strom für deine Maschinen. Elektrisches Licht erhellt deine Industrieanlagen.\n"..
|
||||
"\n"..
|
||||
"TA4: Gegenwart (Present)\n"..
|
||||
"Regenerative Energiequellen wie Wind\\, Sonne und Biokraft helfen dir\\, das Ölzeitalter zu verlassen. Mit modernen Technologien und intelligenten Maschinen machst du dich auf in die Zukunft.\n"..
|
||||
"\n"..
|
||||
"TA5: Zukunft (Future)\n"..
|
||||
"Maschinen zur Überwindung von Raum und Zeit\\, neue Energiequellen und andere Errungenschaften prägen dein Leben.\n"..
|
||||
"\n"..
|
||||
"Hinweis: Mit Klicken auf die Pluszeichen kommst du in die Unterkapitel dieser Anleitung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Diese Dokumentation ist sowohl \"ingame\" (Block Konstruktionsplan) als auch auf GitHub als MD-Files verfügbar.\n"..
|
||||
"\n"..
|
||||
" - Link: https://github.com/joe7575/techage/wiki\n"..
|
||||
"\n"..
|
||||
"Die Konstruktionspläne (Diagramme) für den Aufbau der Maschinen sowie die Bilder sind aber nur ingame verfügbar.\n"..
|
||||
"\n"..
|
||||
"Bei Tech Age musst du von vorne beginnen. Nur mit den Items aus TA1 kannst du TA2 Blöcke herstellen\\, für TA3 benötigst du die Ergebnisse aus TA2\\, usw.\n"..
|
||||
"\n"..
|
||||
"In TA2 laufen die Maschinen nur mit Antriebsachsen.\n"..
|
||||
"\n"..
|
||||
"Ab TA3 laufen die Maschinen mit Strom und besitzen eine Kommunikationsschnittstelle zur Fernsteuerung.\n"..
|
||||
"\n"..
|
||||
"Mit TA4 kommen weitere Stromquellen dazu\\, aber auch höhere logistische Herausforderungen (Stromtrassen\\, Item Transport).\n"..
|
||||
"\n",
|
||||
"Ab V1.0 (17.07.2021) hat sich folgendes geändert:\n"..
|
||||
"\n"..
|
||||
" - Der Algorithmus zur Berechnung der Stromverteilung hat sich geändert. Energiespeichersystem werden dadurch wichtiger. Diese gleichen Schankungen aus\\, was bei größeren Netzen mit mehreren Generatoren wichtig wird.\n"..
|
||||
" - Aus diesem Grund hat TA2 seinen eigenen Energiespeicher erhalten.\n"..
|
||||
" - Die Akkublöcke aus TA3 dienen auch als Energiespeicher. Ihre Funktionsweise wurde entsprechend angepasst.\n"..
|
||||
" - Das TA4 Speichersystem wurde überarbeitet. Die Wärmetauscher (heatexchanger) haben eine neue Nummer bekommen\\, da die Funktionalität vom unteren in den mittleren Block verschoben wurde. Sofern diese ferngesteuert wurden\\, muss die Knotennummer angepasst werden. Die Generatoren haben kein eigenes Menü mehr\\, sondern werden nur noch über den Wärmetauscher ein-/ausgeschaltet. Wärmetauscher und Generator müssen jetzt am gleichen Netz hängen!\n"..
|
||||
" - Mehrere Stromnetze können jetzt über einen TA4 Transformator Blöcke gekoppelt werden.\n"..
|
||||
" - Neu ist auch ein TA4 Stromzähler Block für Unternetze.\n"..
|
||||
"\n",
|
||||
"Viele weitere Blöcke haben kleinere Änderungen bekommen. Daher kann es sein\\, dass Maschinen oder Anlagen nach der Umstellung nicht gleich wieder anlaufen. Sollte es zu Störungen kommen\\, helfen folgende Tipps:\n"..
|
||||
"\n"..
|
||||
" - Maschinen aus- und wieder eingeschalten\n"..
|
||||
" - ein Stromkabel-Block entfernen und wieder setzen\n"..
|
||||
" - den Block ganz entfernen und wieder setzen\n"..
|
||||
" - mindestens ein Akkublock oder Speichersystem in jedes Netzwerk\n"..
|
||||
"\n",
|
||||
"Techage fügt dem Spiel einige neue Items hinzu:\n"..
|
||||
"\n"..
|
||||
" - Meridium - eine Legierung zur Herstellung von leuchtenden Werkzeugen in TA1\n"..
|
||||
" - Usmium - ein Erz\\, was in TA2 gefördert und für TA3 benötigt wird\n"..
|
||||
" - Baborium - ein Metall\\, welches für Rezepte in TA3 benötigt wird\n"..
|
||||
" - Erdöl - wird in TA3 benötigt\n"..
|
||||
" - Bauxit - ein Aluminiumerz\\, was in TA4 zur Herstellung von Aluminium benötigt wird\n"..
|
||||
" - Basalt - entsteht\\, wenn sich Wasser und Lave berühren\n"..
|
||||
"\n",
|
||||
"Meridium ist eine Legierung aus Stahl und Mesekristallen. Meridium Ingots können mit dem Kohlebrenner aus Stahl und Mesesplitter hergestellt werden. Meridium leuchtet im Dunkeln. Auch Werkzeuge aus Meridium leuchten und sind daher im Untertagebau sehr hilfreich.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Usmium kommt nur als Nuggets vor und kann nur beim Waschen von Kies mit der TA2/TA3 Kieswaschanlage gewonnen werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Barborium kann nur im Untertagebau gewonnen werden. Diesen Stoff findet man nur in einer Tiefe von -250 bis -340 Metern.\n"..
|
||||
"Baborium kann nur im TA3 Industrieofen geschmolzen werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Erdöl kann nur mit Hilfe des Explorers gefunden und mit Hilfe entsprechender TA3 Maschinen gefördert werden. Siehe TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Bauxit wird nur im Untertagebau gewonnen. Bauxit findet man nur in Stein in einer Höhe zwischen -50 und -500 Meter.\n"..
|
||||
"Es wird zur Herstellung von Aluminium benötigt\\, was vor allem in TA4 Verwendung findet.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Basalt entsteht nur\\, wenn Lava und Wasser zusammen kommen.\n"..
|
||||
"Dazu sollte man am besten eine Anlage aufbauen\\, bei der eine Lava- und eine Wasserquelle zusammenfließen.\n"..
|
||||
"Dort wo sich beide Flüssigkeiten treffen\\, entsteht Basalt.\n"..
|
||||
"Einen automatisierten Basalt Generator kann man mit dem Sign Bot aufbauen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
"usmium",
|
||||
"baborium",
|
||||
"oil",
|
||||
"bauxite",
|
||||
"basalt",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,Tech Age Mod",
|
||||
"2,Hints",
|
||||
"2,Changes from version 1.0",
|
||||
"3,Tips on switching",
|
||||
"2,Ores and Minerals",
|
||||
"3,Meridium",
|
||||
"3,Usmium",
|
||||
"3,Baborium",
|
||||
"3,Petroleum",
|
||||
"3,Bauxite",
|
||||
"3,Basalt",
|
||||
"2,History",
|
||||
},
|
||||
texts = {
|
||||
"Tech Age is a technology mod with 5 development stages:\n"..
|
||||
"\n"..
|
||||
"TA1: Iron Age\n"..
|
||||
"Use tools and aids such as coal burners\\, coal burners\\, gravel sieves\\, hammers and hoppers to mine and process the necessary ores and metals.\n"..
|
||||
"\n"..
|
||||
"TA2: Steam Age\n"..
|
||||
"Build a steam engine with drive axles and use it to operate your first ore processing machines.\n"..
|
||||
"\n"..
|
||||
"TA3: Oil Age\n"..
|
||||
"Find and extract oil\\, built railways for oil transportation. A power plant provides the necessary electricity for your machines. Electric light illuminates your industrial plants.\n"..
|
||||
"\n"..
|
||||
"TA4: Present\n"..
|
||||
"Renewable energy sources such as wind\\, sun and bio-fuels help you to leave the oil age. With modern technologies and intelligent machines you set out into the future.\n"..
|
||||
"\n"..
|
||||
"TA5: Future\n"..
|
||||
"Machines to overcome space and time\\, new sources of energy and other achievements shape your life.\n"..
|
||||
"\n"..
|
||||
"Note: With a click on the plus sign you get into the sub-chapters of this manual.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"This documentation is available both \"ingame\" (block construction plan) and on GitHub as MD files.\n"..
|
||||
"\n"..
|
||||
" - Link: https://github.com/joe7575/techage/wiki\n"..
|
||||
"\n"..
|
||||
"The construction plans (diagrams) for the construction of the machines and the pictures are only available in-game.\n"..
|
||||
"\n"..
|
||||
"With Tech Age you have to start over. You can only create TA2 blocks with the items from TA1\\, for TA3 you need the results from TA2\\, etc.\n"..
|
||||
"\n"..
|
||||
"In TA2\\, the machines only run with drive axes.\n"..
|
||||
"\n"..
|
||||
"From TA3\\, the machines run on electricity and have a communication interface for remote control.\n"..
|
||||
"\n"..
|
||||
"TA4 adds more power sources\\, but also higher logistical challenges (power lines\\, item transport).\n"..
|
||||
"\n",
|
||||
"From V1.0 (07/17/2021) the following has changed:\n"..
|
||||
"\n"..
|
||||
" - The algorithm for calculating the power distribution has changed. This makes energy storage systems more important. These compensate for fluctuations\\, which is important in larger networks with several generators.\n"..
|
||||
" - For this reason TA2 got its own energy storage.\n"..
|
||||
" - The battery blocks from TA3 also serve as energy storage. Their functionality has been adapted accordingly.\n"..
|
||||
" - The TA4 storage system has been revised. The heat heat exchanger have been given a new number because the functionality has been moved from the lower to the middle block. If these were remotely controlled\\, the node number must be adapted. The generators no longer have their own menu\\, but are only switched on / off via the heat exchanger. The heat exchanger and generator must now be connected to the same network!\n"..
|
||||
" - Several power grids can now be coupled via a TA4 transformer blocks.\n"..
|
||||
" - A TA4 electricity meter block for sub-networks is also new.\n"..
|
||||
" - At least one battery block or a storage system in each network\n"..
|
||||
"\n",
|
||||
"Many more blocks have received minor changes. It is therefore possible that machines or systems do not start up again immediately after the changeover. In the event of malfunctions\\, the following tips will help:\n"..
|
||||
"\n"..
|
||||
" - Switch machines off and on again\n"..
|
||||
" - remove a power cable block and put it back in place\n"..
|
||||
" - remove the block completely and put it back in place\n"..
|
||||
"\n",
|
||||
"Techage adds some new items to the game:\n"..
|
||||
"\n"..
|
||||
" - Meridium - an alloy for the production of luminous tools in TA1\n"..
|
||||
" - Usmium - an ore that is mined in TA2 and needed for TA3\n"..
|
||||
" - Baborium - a metal that is needed for recipes in TA3\n"..
|
||||
" - Petroleum - is needed in TA3\n"..
|
||||
" - Bauxite - an aluminum ore that is needed in TA4 to produce aluminum\n"..
|
||||
" - Basalt - arises when water and lave touch\n"..
|
||||
"\n",
|
||||
"Meridium is an alloy of steel and mesecons crystals. Meridium ingots can be made with the coal burner from steel and mesecons crystals. Meridium glows in the dark. Tools made of Meridium also light up and are therefore very helpful in underground mining.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Usmium only occurs as nuggets and can only be obtained by washing gravel with the TA2/TA3 gravel washing system.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Barborium can only be obtained from underground mining. This substance can only be found at a depth of -250 to -340 meters.\n"..
|
||||
"\n"..
|
||||
"Baborium can only be melted in the TA3 Industrial Furnace.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Petroleum can only be found with the help of the Explorer and extracted with the help of appropriate TA3 machines. See TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Bauxite is only extracted in underground mining. Bauxite is only found in stone at a height between -50 and -500 meters.\n"..
|
||||
"It is required for the production of aluminum\\, which is mainly used in TA4.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Basalt is only created when lava and water come together.\n"..
|
||||
"The best thing to do is to set up a system where a lava and a water source flow together.\n"..
|
||||
"Basalt is formed where both liquids meet.\n"..
|
||||
"You can build an automated basalt generator with the Sign Bot.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
" - 28.09.2019: Solar system added\n"..
|
||||
" - 05.10.2019: Data on the solar system and description of the inverter and the power terminal changed\n"..
|
||||
" - 18.11.2019: Chapter for ores\\, reactor\\, aluminum\\, silo\\, bauxite\\, furnace heating\\, gravel washing system added\n"..
|
||||
" - 22.02.2020: corrections and chapters on the update\n"..
|
||||
" - 29.02.2020: ICTA controller added and further corrections\n"..
|
||||
" - 14.03.2020 Lua controller added and further corrections\n"..
|
||||
" - 22.03.2020 More TA4 blocks added\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
"usmium",
|
||||
"baborium",
|
||||
"oil",
|
||||
"bauxite",
|
||||
"basalt",
|
||||
"",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,Tech Age Mod",
|
||||
"2,Подсказки",
|
||||
"2,Изменения по сравнению с версией 1.0",
|
||||
"3,Советы по переключению",
|
||||
"2,Руды и минералы",
|
||||
"3,Меридий",
|
||||
"3,Усмий",
|
||||
"3,Баборий",
|
||||
"3,Нефть",
|
||||
"3,Боксит",
|
||||
"3,Базальт",
|
||||
"2,History",
|
||||
},
|
||||
texts = {
|
||||
"Tech Age - это технологический мод с 5 стадиями развития:\n"..
|
||||
"\n"..
|
||||
"TA1: Железный век\n"..
|
||||
"Используйте инструменты и приспособления\\, такие как угольные горелки\\, угольные горелки\\, гравийные сита\\, молоты и бункеры\\, чтобы добывать и обрабатывать необходимые руды и металлы.\n"..
|
||||
"\n"..
|
||||
"TA2: Паровой век\n"..
|
||||
"Постройте паровой двигатель с ведущими осями и используйте его для работы своих первых машин по переработке руды.\n"..
|
||||
"\n"..
|
||||
"TA3: Нефтяной век\n"..
|
||||
"Найдите и добывайте нефть\\, постройте железные дороги для транспортировки нефти. Электростанция дает необходимое электричество для ваших машин. Электрический свет освещает ваши промышленные предприятия.\n"..
|
||||
"\n"..
|
||||
"TA4: Настоящее время\n"..
|
||||
"Возобновляемые источники энергии\\, такие как ветер\\, солнце и биотопливо\\, помогают вам покинуть нефтяной век. С помощью современных технологий и умных машин вы отправляетесь в будущее.\n"..
|
||||
"\n"..
|
||||
"TA5: Будущее\n"..
|
||||
"Машины\\, преодолевающие пространство и время\\, новые источники энергии и другие достижения определяют вашу жизнь.\n"..
|
||||
"\n"..
|
||||
"Примечание: Нажав на знак \"плюс\"\\, вы попадаете в подразделы этого руководства.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Эта документация доступна как \"в игре\" (план строительства блоков)\\, так и на GitHub в виде MD-файлов.\n"..
|
||||
"\n"..
|
||||
" - Ссылка: https://github.com/joe7575/techage/wiki\n"..
|
||||
"\n"..
|
||||
"Строительные планы (схемы) для постройки машин и картинки доступны только в игре.\n"..
|
||||
"\n"..
|
||||
"В Tech Age вам придется начинать все сначала. Вы можете создавать блоки TA2 только с помощью предметов из TA1\\, для TA3 вам нужны результаты из TA2 и т.д.\n"..
|
||||
"\n"..
|
||||
"В TA2 машины работают только с приводными осями.\n"..
|
||||
"\n"..
|
||||
"В TA3 машины работают от электричества и имеют коммуникационный интерфейс для дистанционного управления.\n"..
|
||||
"\n"..
|
||||
"TA4 добавляет больше источников энергии\\, но также и более сложные логистические задачи (линии электропередач\\, транспортировка изделий).\n"..
|
||||
"\n",
|
||||
"С версии 1.0 (07/17/2021) изменилось следующее:\n"..
|
||||
"\n"..
|
||||
" - Изменился алгоритм расчета распределения энергии. Это делает системы хранения энергии более важными. Они компенсируют колебания\\, что важно для больших сетей с несколькими генераторами.\n"..
|
||||
" - По этой причине TA2 обзавелась собственным накопителем энергии.\n"..
|
||||
" - Аккумуляторные блоки из TA3 также служат в качестве накопителей энергии. Их функциональность была соответствующим образом адаптирована.\n"..
|
||||
" - Система хранения TA4 была пересмотрена. Теплообменник получил новый номер\\, поскольку его функциональность была перенесена с нижнего на средний блок. Если они управлялись дистанционно\\, номер узла должен быть адаптирован. Генераторы больше не имеют собственного меню\\, а включаются/выключаются только через теплообменник. Теплообменник и генератор теперь должны быть подключены к одной сети!\n"..
|
||||
" - Несколько электросетей теперь могут быть соединены через трансформаторные блоки TA4.\n"..
|
||||
" - Также появился блок счетчиков электроэнергии TA4 для подсетей.\n"..
|
||||
" - Как минимум один блок аккумуляторов или система хранения в каждой сети\n"..
|
||||
"\n",
|
||||
"Многие другие блоки получили незначительные изменения. Поэтому возможно\\, что машины или системы не будут запускаться сразу после переключения. В случае неполадок помогут следующие советы:\n"..
|
||||
"\n"..
|
||||
" - выключите и снова включите машины\n"..
|
||||
" - снимите блок силовых кабелей и установите его на место\n"..
|
||||
" - полностью снимите блок и установите его на место\n"..
|
||||
"\n",
|
||||
"Techage добавляет в игру несколько новых предметов:\n"..
|
||||
"\n"..
|
||||
" - Меридий - сплав для производства светящихся инструментов в TA1\n"..
|
||||
" - Усмий - руда\\, которая добывается в TA2 и необходима для TA3\n"..
|
||||
" - Бабориум - металл\\, необходимый для рецептов в TA3\n"..
|
||||
" - Нефть - необходима в TA3\n"..
|
||||
" - Боксит - алюминиевая руда\\, которая необходима в TA4 для производства алюминия\n"..
|
||||
" - Базальт - возникает при соприкосновении воды и лав\n"..
|
||||
"\n",
|
||||
"Меридий - это сплав стали и кристаллов мезекона. Слитки меридиума можно изготовить с помощью угольной горелки из стали и кристаллов мезекона. Меридий светится в темноте. Инструменты из меридиума также светятся и поэтому очень полезны при подземной добыче.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Усмий встречается только в виде самородков и может быть получен только при промывке гравия с помощью системы промывки гравия TA2/TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Барборий можно получить только при подземной добыче. Это вещество можно найти только на глубине от -250 до -340 метров.\n"..
|
||||
"\n"..
|
||||
"Бабориум можно переплавить только в промышленной печи TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Нефть можно найти только с помощью Исследователя и добыть с помощью соответствующих машин TA3. См. TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Боксит можно добыть только в подземной шахте. Боксит можно найти только в камне на высоте от -50 до -500 метров.\n"..
|
||||
"Он необходим для производства алюминия\\, который в основном используется в TA4.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Базальт образуется только при соединении лавы и воды.\n"..
|
||||
"Лучше всего создать систему\\, в которой лава и вода будут течь вместе.\n"..
|
||||
"Базальт образуется там\\, где встречаются обе жидкости.\n"..
|
||||
"Вы можете создать автоматический генератор базальта с помощью Sign Bot.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
" - 28.09.2019: Solar system added\n"..
|
||||
" - 05.10.2019: Data on the solar system and description of the inverter and the power terminal changed\n"..
|
||||
" - 18.11.2019: Chapter for ores\\, reactor\\, aluminum\\, silo\\, bauxite\\, furnace heating\\, gravel washing system added\n"..
|
||||
" - 22.02.2020: corrections and chapters on the update\n"..
|
||||
" - 29.02.2020: ICTA controller added and further corrections\n"..
|
||||
" - 14.03.2020 Lua controller added and further corrections\n"..
|
||||
" - 22.03.2020 More TA4 blocks added\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
"usmium",
|
||||
"baborium",
|
||||
"oil",
|
||||
"bauxite",
|
||||
"basalt",
|
||||
"",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,Mod Tech Age",
|
||||
"2,TA1: Idade do Ferro",
|
||||
"2,TA2: Idade do Vapor",
|
||||
"2,TA3: Idade do Petróleo",
|
||||
"2,TA4: Tempos atuais (Presente)",
|
||||
"2,TA5: Futuro",
|
||||
"1,Dicas",
|
||||
"1,Mudanças a partir da versão 1.0",
|
||||
"2,Dicas sobre a troca",
|
||||
"1,Minérios e Minerais",
|
||||
"2,Meridium",
|
||||
"2,Usmium",
|
||||
"2,Baborium",
|
||||
"2,Petróleo",
|
||||
"2,Bauxita",
|
||||
"2,Basalto",
|
||||
"2,History",
|
||||
},
|
||||
texts = {
|
||||
"O Tech Age é um mod de tecnologia com 5 estágios de desenvolvimento:\n"..
|
||||
"\n",
|
||||
"Utilize ferramentas e instrumentos auxiliares como queimadores de carvão\\, peneiras de cascalho\\, martelos e funis para extrair e processar minérios e metais necessários.\n"..
|
||||
"\n",
|
||||
"Construa uma máquina a vapor com eixos de transmissão e use-a para operar suas primeiras máquinas de processamento de minérios.\n"..
|
||||
"\n",
|
||||
"Encontre e extraia óleo\\, construa ferrovias para transporte de óleo. Uma usina fornece a eletricidade necessária para suas máquinas. A luz elétrica ilumina suas instalações industriais.\n"..
|
||||
"\n",
|
||||
"Fontes de energia renovável\\, como vento\\, sol e biocombustíveis\\, ajudam você a sair da era do petróleo. Com tecnologias modernas e máquinas inteligentes\\, você parte para o futuro.\n"..
|
||||
"\n",
|
||||
"Máquinas para superar espaço e tempo\\, novas fontes de energia e outras conquistas moldam sua vida.\n"..
|
||||
"\n"..
|
||||
"Nota: Clicando no sinal de adição\\, você acessa os subcapítulos deste manual.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Esta documentação está disponível tanto \"dentro do jogo\" (plano de construção de blocos) quanto no GitHub como arquivos MD.\n"..
|
||||
"\n"..
|
||||
" - Link: https://github.com/joe7575/techage/wiki\nOs planos de construção (diagramas) para a construção das máquinas e as imagens estão disponíveis apenas no jogo.\n"..
|
||||
"\n"..
|
||||
"Com o Tech Age\\, você precisa começar do zero. Você só pode criar blocos TA2 com os itens do TA1\\, para o TA3 você precisa dos resultados do TA2\\, e assim por diante.\n"..
|
||||
"\n"..
|
||||
"No TA2\\, as máquinas só funcionam com eixos de transmissão.\n"..
|
||||
"\n"..
|
||||
"A partir do TA3\\, as máquinas funcionam com eletricidade e têm uma interface de comunicação para controle remoto.\n"..
|
||||
"\n"..
|
||||
"O TA4 adiciona mais fontes de energia\\, mas também desafios logísticos mais altos (linhas de energia\\, transporte de itens).\n"..
|
||||
"\n",
|
||||
"A partir da V1.0 (17/07/2021)\\, as seguintes alterações foram feitas:\n"..
|
||||
"\n"..
|
||||
" - O algoritmo para calcular a distribuição de energia foi alterado. Isso torna os sistemas de armazenamento de energia mais importantes. Eles compensam as flutuações\\, o que é importante em redes maiores com vários geradores.\n"..
|
||||
" - Por esse motivo\\, o TA2 recebeu seu próprio sistema de armazenamento de energia.\n"..
|
||||
" - Os blocos de bateria do TA3 também servem como armazenamento de energia. Sua funcionalidade foi adaptada de acordo.\n"..
|
||||
" - O sistema de armazenamento do TA4 foi revisado. O permutador de calor recebeu um novo número porque a funcionalidade foi movida do bloco inferior para o bloco central. Se eles estiverem sendo controlados remotamente\\, o número do nó deve ser adaptado. Os geradores não têm mais um menu próprio\\, mas são ligados/desligados apenas através do permutador de calor. O permutador de calor e o gerador agora devem estar conectados à mesma rede!\n"..
|
||||
" - Vários sistemas de energia podem agora ser acoplados via blocos transformadores TA4.\n"..
|
||||
" - Um novo bloco medidor de eletricidade TA4 para sub-redes também foi adicionado.\n"..
|
||||
" - Pelo menos um bloco de bateria ou um sistema de armazenamento em cada rede.\n"..
|
||||
"\n",
|
||||
"Muitos outros blocos receberam alterações menores. Portanto\\, é possível que máquinas ou sistemas não reiniciem imediatamente após a troca. Em caso de falhas\\, as seguintes dicas ajudarão:\n"..
|
||||
"\n"..
|
||||
" - Desligue e ligue as máquinas novamente.\n"..
|
||||
" - Remova um bloco de cabo de energia e coloque-o de volta no lugar.\n"..
|
||||
" - Remova completamente o bloco e coloque-o de volta no lugar.\n"..
|
||||
"\n",
|
||||
"Techage adiciona novos itens ao jogo:\n"..
|
||||
"\n"..
|
||||
" - Meridium - uma liga para a produção de ferramentas luminosas no TA1\n"..
|
||||
" - Usmium - um minério que é extraído no TA2 e necessário para o TA3\n"..
|
||||
" - Baborium - um metal necessário para receitas no TA3\n"..
|
||||
" - Petróleo - necessário no TA3\n"..
|
||||
" - Bauxita - um minério de alumínio necessário no TA4 para produzir alumínio\n"..
|
||||
" - Basalto - surge quando água e lava se encontram\n"..
|
||||
"\n",
|
||||
"O Meridium é uma liga de aço e cristais de mesecons. Lingotes de Meridium podem ser feitos com a caldeira a carvão a partir de aço e cristais de mesecons. O Meridium brilha no escuro. Ferramentas feitas de Meridium também emitem luz e são\\, portanto\\, muito úteis na mineração subterrânea.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O Usmium ocorre apenas como pepitas e só pode ser obtido lavando cascalho com o sistema de lavagem de cascalho TA2/TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O Baborium só pode ser obtido através da mineração subterrânea. Essa substância só pode ser encontrada a uma profundidade de -250 a -340 metros.\n"..
|
||||
"\n"..
|
||||
"O Baborium só pode ser derretido na Fornalha Industrial TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O Petróleo só pode ser encontrado com a ajuda do Explorer e extraído com a ajuda de máquinas apropriadas do TA3. Veja TA3.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"A Bauxita é extraída apenas na mineração subterrânea. A Bauxita só é encontrada na pedra a uma altura entre -50 e -500 metros.\n"..
|
||||
"É necessária para a produção de alumínio\\, que é principalmente usada no TA4.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O Basalto só é criado quando lava e água se encontram.\n"..
|
||||
"A melhor coisa a fazer é montar um sistema onde uma fonte de lava e uma fonte de água se encontram.\n"..
|
||||
"O Basalto é formado onde ambos os líquidos se encontram.\n"..
|
||||
"Você pode construir um gerador automático de basalto com o Sign Bot.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
" - 28.09.2019: Solar system added\n"..
|
||||
" - 05.10.2019: Data on the solar system and description of the inverter and the power terminal changed\n"..
|
||||
" - 18.11.2019: Chapter for ores\\, reactor\\, aluminum\\, silo\\, bauxite\\, furnace heating\\, gravel washing system added\n"..
|
||||
" - 22.02.2020: corrections and chapters on the update\n"..
|
||||
" - 29.02.2020: ICTA controller added and further corrections\n"..
|
||||
" - 14.03.2020 Lua controller added and further corrections\n"..
|
||||
" - 22.03.2020 More TA4 blocks added\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"techage_ta4",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"meridium",
|
||||
"usmium",
|
||||
"baborium",
|
||||
"oil",
|
||||
"bauxite",
|
||||
"basalt",
|
||||
"",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,TA1: Eisenzeitalter",
|
||||
"2,Köhler / Coal Pile",
|
||||
"2,Kohlebrenner / Coal Burner",
|
||||
"2,Wassermühle",
|
||||
"3,TA1 Mühle",
|
||||
"3,TA1 Schleusenschieber / TA1 Sluice Gate",
|
||||
"3,TA1 Schleusengriff / TA1 Sluice Handle",
|
||||
"3,TA1 Apfelholzbrett / TA1 Apple Wood Board",
|
||||
"3,TA1 Apfel Mühlbachbrett / TA1 Apple Millrace Board",
|
||||
"2,Erze und Werkzeuge",
|
||||
"3,Hammer",
|
||||
"3,Kiessieb / Gravel Sieve",
|
||||
"3,Trichter / Hopper",
|
||||
"3,Kies sieben mit dem Trichter",
|
||||
"3,Meridium",
|
||||
},
|
||||
texts = {
|
||||
"In TA1 geht es darum\\, mit einfachen Werkzeugen und Gerätschaften ausreichend Erze zu schürfen und Holzkohle herzustellen\\, so dass damit TA2 Maschinen hergestellt und betrieben werden können.\n"..
|
||||
"\n"..
|
||||
"Natürlich muss es für ein Eisenzeitalter auch Eisen geben und nicht nur Stahl (steel)\\, wie in \"Minetest Game\". Daher wurden einige Rezepte geändert\\, so dass zuerst Eisen hergestellt werden muss und erst später dann Stahl.\n"..
|
||||
"\n"..
|
||||
"Auch ist die Haltbarkeit der Werkzeuge an die Zeitalter angelehnt und entspricht damit nicht dem Minetest Originalspiel.\n"..
|
||||
"Die Haltbarkeit/Härte bspw. für eine Axt ist:\n"..
|
||||
"\n"..
|
||||
" - Bronze: 20\n"..
|
||||
" - Stahl: 30\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Den Köhler brauchst du\\, um Holzkohle herzustellen. Holzkohle wird für den Brenner\\, aber auch bspw. in TA2 für die Dampfmaschine benötigt.\n"..
|
||||
"\n"..
|
||||
"Für den Köhler brauchst du:\n"..
|
||||
"\n"..
|
||||
" - einen Anzünderblock ('techage:lighter')\n"..
|
||||
" - 26 Hölzblöcke (wood)\\, die zu einem Würfen aufgeschichtet werden. Die Holzsorte spielt keine Rolle.\n"..
|
||||
" - Erde (dirt) um den Holzhaufen abzudecken.\n"..
|
||||
" - Feuerstein und Eisen (technischer Name: 'fire:flint_and_steel') um den Anzünderblock anzuzünden.\n"..
|
||||
"\n"..
|
||||
"Bauanleitung (siehe auch Plan):\n"..
|
||||
"\n"..
|
||||
" - Baue eine 5x5 große Fläche aus Erde (dirt)\n"..
|
||||
" - Platziere in die Mitte einen Anzünder (lighter)\n"..
|
||||
" - Platziere rund um den Anzünder 7 Holz (wood)\\, aber lasse ein Loch zum Anzünder frei\n"..
|
||||
" - Baue weitere 2 Schichten Holz darüber\\, so dass ein 3x3x3 großer Holzwürfel entsteht\n"..
|
||||
" - Überdecke alles mit einer Schicht Erde zu einem 5x5x5 großen Würfel\\, aber lasse das Loch zum Anzünder frei\n"..
|
||||
" - Entzünde den Anzünder und verschließe das Loch sofort mit jeweils einem Block Holz und Erde\n"..
|
||||
" - Wenn du alles richtig gemacht hast\\, fängt der Köhler nach wenigen Sekunden an zu rauchen\n"..
|
||||
" - Öffne den Köhler erst\\, wenn der Rauch verschwunden ist (ca. 20 min)\n"..
|
||||
"\n"..
|
||||
"Dann kannst du die 9 Holzkohleblöcke entnehmen und den Köhler erneut füllen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Den Kohlebrenner benötigst du bspw. um Eisen und andere Erze im Schmelztiegel zu schmelzen. Es gibt verschiedene Rezepte\\, welche verschiedene Temperaturen benötigen. Je höher der Turm\\, um so heißer ist die Flamme. Eine Höhe von 11 Blöcken über der Bodenplatte ist für alle Rezepte ausreichend\\, ein Brenner mit dieser Höhe verbraucht aber auch mehr Holzkohle.\n"..
|
||||
"\n"..
|
||||
"Bauanleitung (siehe auch Plan):\n"..
|
||||
"\n"..
|
||||
" - Baue einen Turm aus Stein (cobble) mit einer 3x3 Grundfläche (7-11 Blöcke hoch)\n"..
|
||||
" - Lasse unten ein Loch an einer Seite offen\n"..
|
||||
" - Lege einen Anzünder (lighter) hinein\n"..
|
||||
" - Fülle den Turm bis zum Rand mit Holzkohle\\, in dem du die Holzkohle von oben in das Loch fallen lässt\n"..
|
||||
" - Entzünde den Anzünder durch das Loch\n"..
|
||||
" - Platziere den Schmelztiegel oben auf dem Turm direkt in die Flamme\\, einen Block über dem Turmrand\n"..
|
||||
" - Um den Brenner anzuhalten\\, schließe das Loch vorübergehend bspw. mit einem Erdblock.\n"..
|
||||
"\n"..
|
||||
"Der Schmelztiegel hat ein eigenes Menü mit Rezepten und ein Inventar\\, wo du die Erze hinein legst.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden. Die Mühle wird mit\n"..
|
||||
"Wasserkraft angetrieben. Dazu muss ein Mühlbach über einen Kanal zum Mühlrad geführt werden.\n"..
|
||||
"Über eine Schleuse kann der Wasserfluss und damit das Mühlrad gesteuert werden.\n"..
|
||||
"Die Schleuse besteht aus Schleusenschieber und Schleusengriff.\n"..
|
||||
"\n"..
|
||||
"Die Abbildung rechts (auf \"Plan\" klicken) zeigt den Aufbau der Wassermühle.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit der Wassermühle können Weizen und andere Getreide zu Mehl gemahlen und dann im Ofen zu Brot gebacken werden.\n"..
|
||||
"Die Mühle muss mit einer TA1 Achse mit dem Mühlrad verbunden werden. Die Kraft des Mühlrades reicht nur für eine Mühle.\n"..
|
||||
"\n"..
|
||||
"Die Mühle kann mit Hilfe eines Minecart Hoppers automatisiert werden\\, so dass das Mehl bspw. direkt von der Mühle in einen Ofen befördert wird\\, um daraus Brot zu backen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der Schleusenschieber muss auf gleicher Höhe wie die Wasseroberfläche direkt an einen Teich oder in einen Bach gesetzt werden.\n"..
|
||||
"Wird die Schleuse geöffnet\\, so fließt Wasser durch den Schieber. Dieses Wasser muss dann zum Mühlrad geleitet werden und treibt dort die Mühle an.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der TA1 Schleusengriff muss auf den Schleusenschieber gesetzt werden. Mit Hilfe des Schleusengriffs (Rechtsklick) kann der Schieber geöffnet werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Block in verschiedenen Holzsorten zum Bauen des Mühlbachkanals. Es kann aber auch jedes andere Material verwendet werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Block in verschiedenen Holzsorten zum Bauen des Mühlbachkanals. Dieser Block eignet sich speziell in Verbindung mit den Pfosten des Holzzauns um eine Stütze für den Kanal zu bauen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 hat seine eigenen Werkzeuge wie Hammer und Kiessieb\\, aber auch der Minecart Hopper kann genutzt werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit dem TA1 Hammer können Steine (stone) und Kopfsteinpflaster-Steine (cobble) zu Kies (gravel) zertrümmert werden. Der Hammer ist in verschiedenen Ausführungen und damit verschiedenen Eigenschaften verfügbar: Bronze\\, Stahl\\, Mese und Diamant.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit dem Kiessieb können Erze aus dem Kies gesiebt werden. Dazu mit dem Kies (gravel) auf das Sieb klicken. Der gesiebte Kies und die Erze fallen unten heraus.\n"..
|
||||
"\n"..
|
||||
"Um hier nicht stundenlang am Sieb zu stehen\\, kann das Sieben mit dem Trichter (hopper) automatisiert werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der Hopper aus der Mod \"Minecart\" dient in erster Linie zum Be- und Entladen von Minecarts. Er saugt Gegenstände (items) von oben ein und gibt diese nach rechts weiter. Beim Platzieren des Trichters muss daher auf die Ausgaberichtung geachtet werden.\n"..
|
||||
"\n"..
|
||||
"Der Trichter kann aber auch Items aus Kisten (chest) ziehen\\, sofern die Kiste neben oder auf dem Trichter steht. \n"..
|
||||
"\n"..
|
||||
"Der Trichter kann auch Items in Kisten legen\\, sofern die Kiste neben dem Trichter steht.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit Hilfe von zwei Kisten\\, zwei Trichtern und einem Kiessieb kann der Siebevorgang automatisiert werden. Der Plan rechts zeigt den Aufbau.\n"..
|
||||
"\n"..
|
||||
"Bei den Kisten darauf achten\\, dass es die \"chest_locked\" ist\\, sonst klaut dir jemand die wertvollen Erze aus der Kiste unten.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 hat seine eigene Metalllegierung Meridium. Meridium Ingots können mit dem Kohlebrenner aus Stahl und Mesesplittern hergestellt werden. Meridium leuchtet im Dunkeln. Auch Werkzeuge aus Meridium leuchten und sind daher im Untertagebau sehr hilfreich.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta1",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta1_sluice",
|
||||
"ta1_sluice_handle",
|
||||
"ta1_board1",
|
||||
"ta1_board2",
|
||||
"ta1_gravelsieve",
|
||||
"hammer",
|
||||
"ta1_gravelsieve",
|
||||
"ta1_hopper",
|
||||
"",
|
||||
"meridium",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"coalpile",
|
||||
"coalburner",
|
||||
"watermill1",
|
||||
"watermill2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"hoppersieve",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,TA1: Iron Age",
|
||||
"2,Charcoal Pile (charcoal burner)",
|
||||
"2,Melting Furnace",
|
||||
"2,Watermill",
|
||||
"3,TA1 mill",
|
||||
"3,TA1 sluice gate",
|
||||
"3,TA1 sluice handle",
|
||||
"3,TA1 Apple Wood Board",
|
||||
"3,TA1 Apple Millrace Board",
|
||||
"2,Ores and Tools",
|
||||
"3,Hammer",
|
||||
"3,Gravel Sieve",
|
||||
"3,Hopper",
|
||||
"3,Gravel seven with the hopper",
|
||||
"3,Meridium",
|
||||
},
|
||||
texts = {
|
||||
"TA1 is about mining sufficient ores and producing charcoal with simple tools and equipment\\, so that TA2 machines can be manufactured and operated.\n"..
|
||||
"\n"..
|
||||
"Of course\\, for an iron age there must also be iron and not just steel\\, as in \"Minetest Game\". As a result\\, some recipes have been changed so that iron has to be produced first and then steel later.\n"..
|
||||
"\n"..
|
||||
"The durability of the tools is based on the ages and therefore does not correspond to the original Minetest game.\n"..
|
||||
"The durability / hardness for an axe\\, for example:\n"..
|
||||
"\n"..
|
||||
" - Bronze: 20\n"..
|
||||
" - Steel: 30\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"You need the Charcoal Pile to make charcoal. Charcoal is required for the melting furnace\\, but also\\, for example\\, in TA2 for the steam engine.\n"..
|
||||
"\n"..
|
||||
"For the charcoal burner you need:\n"..
|
||||
"\n"..
|
||||
" - a lighter block ('techage:lighter')\n"..
|
||||
" - 26 wooden blocks that are stacked into a pile of wood. The type of wood is irrelevant\n"..
|
||||
" - Dirt to cover the pile of wood\n"..
|
||||
" - Flint and Iron (technical name: 'fire:flint_and_steel') to light the lighter block\n"..
|
||||
"\n"..
|
||||
"Building instructions (see also plan):\n"..
|
||||
"\n"..
|
||||
" - Build a 5x5 area of dirt\n"..
|
||||
" - Place 7 wood around the lighter but leave a hole to the lighter\n"..
|
||||
" - Build another 2 layers of wood on top\\, making a 3x3x3 wooden cube\n"..
|
||||
" - Cover everything with a layer of dirt into a 5x5x5 cube\\, but keep the hole to the lighter open\n"..
|
||||
" - Light the lighter and immediately close the hole with a block of wood and dirt\n"..
|
||||
" - If you have done everything correctly\\, the coal burner will start smoking after a few seconds\n"..
|
||||
" - Only open the charcoal burner when the smoke has disappeared (approx. 20 min)\n"..
|
||||
"\n"..
|
||||
"Then you can remove the 9 charcoal blocks and refill the Charcoal Pile.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"You need the melting furnace\\, for example\\, to melt iron and other ores in the melting pot. There are different recipes that require different temperatures. The higher the melting tower\\, the hotter the flame. A height of 11 blocks above the base plate is for all recipes\\, but a burner with this height also requires more charcoal.\n"..
|
||||
"\n"..
|
||||
"Building instructions (see also plan):\n"..
|
||||
"\n"..
|
||||
" - Build a stone tower (cobble) with a 3x3 base (7-11 blocks high)\n"..
|
||||
" - Leave a hole open on one side at the bottom\n"..
|
||||
" - Put a lighter in it\n"..
|
||||
" - Fill the tower to the brim with charcoal by dropping the charcoal into the hole from above\n"..
|
||||
" - Light the lighter through the hole\n"..
|
||||
" - Place the melting pot on top of the tower directly into the flame\\, one block above the tower edge\n"..
|
||||
" - To stop the burner\\, temporarily close the hole with an dirt block\\, for example.\n"..
|
||||
"\n"..
|
||||
"The melting pot has its own menu of recipes and an inventory where you have to put the ores in.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The watermill can be used to grind wheat and other grains into flour and then bake them in the furnace to make bread. \n"..
|
||||
"The mill is powered by water power. To do this\\, a millrace must be led to the mill wheel via a canal.\n"..
|
||||
"The water flow and thus the mill wheel can be controlled via a sluice. The sluice consists of the sluice lock and sluice handle.\n"..
|
||||
"\n"..
|
||||
"The picture on the right (click on \"Plan\") shows the structure of the watermill. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The watermill can be used to grind wheat and other grains into flour and then bake them in the oven to make bread. The mill must be connected to the mill wheel with a TA1 axle. The power of the mill wheel is only enough for one mill.\n"..
|
||||
"\n"..
|
||||
"The mill can be automated with the help of a Minecart Hopper\\, so that the flour\\, for example\\, is transported directly from the mill into an furnace in order to bake bread from it.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The sluice gate valve must be placed directly next to a pond or in a stream at the same height as the water surface.\n"..
|
||||
"When the gate is opened\\, water flows through the slide. This water then has to be fed to the mill wheel\\, where it drives the mill.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA1 sluice handle must be placed on the sluice gate. The gate can be opened with the aid of the sluice handle (right click).\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Block in different types of wood for building the millrace canal. However\\, any other material can also be used.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Block in different types of wood for building the millrace canal. This block is especially suitable in connection\n"..
|
||||
"with posts of the wooden fence to build a support of the canal.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 has its own tools such as hammer and gravel sieve\\, but the Minecart Hopper can also be used.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The TA1 hammer can be used to knock/dig stone in a mine\\, but also to smash cobble to gravel. The hammer is available in different versions and therefore different properties: bronze\\, steel\\, brass and diamond.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Ores can be sifted from the gravel with the gravel sieve. To do this\\, click on the sieve with the gravel. The sifted gravel and ores fall out below.\n"..
|
||||
"\n"..
|
||||
"In order not to stand at the sieve for hours\\, sieving can be automated with the hopper.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"The hopper from the \"Minecart\" mod is primarily used for loading and unloading Minecarts. He sucks in items from above and passes them on to the right. Therefore\\, when placing the hopper\\, pay attention to the direction of dispensing.\n"..
|
||||
"\n"..
|
||||
"The hopper can also pull items from boxes (chest)\\, provided the box is next to or on the hopper.\n"..
|
||||
"\n"..
|
||||
"The hopper can also put items in boxes if the box is next to the hopper.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"With the help of two boxes\\, two hoppers and a gravel sieve\\, the sieving process can be automated. The plan on the right shows the structure.\n"..
|
||||
"\n"..
|
||||
"Make sure that the boxes are \"chest_locked\"\\, otherwise someone will steal the valuable ores from the box below.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 has its own metal alloy meridium. Meridium ingots can be made with the coal burner from steel and mesecons crystals. Meridium glows in the dark. Tools made of Meridium also light up and are therefore very helpful in underground mining.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta1",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta1_sluice",
|
||||
"ta1_sluice_handle",
|
||||
"ta1_board1",
|
||||
"ta1_board2",
|
||||
"ta1_gravelsieve",
|
||||
"hammer",
|
||||
"ta1_gravelsieve",
|
||||
"ta1_hopper",
|
||||
"",
|
||||
"meridium",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"coalpile",
|
||||
"coalburner",
|
||||
"watermill1",
|
||||
"watermill2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"hoppersieve",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,TA1: Эпоха железа",
|
||||
"2,Углевыжигательная куча (древесноугольная печь)",
|
||||
"2,Плавильная печь",
|
||||
"2,Водяная мельница",
|
||||
"3,TA1 мельница",
|
||||
"3,TA1 шлюзовой затвор",
|
||||
"3,TA1 шлюзовой рычаг",
|
||||
"3,TA1 яблоневая доска",
|
||||
"3,TA1 яблоневая мельничная доска",
|
||||
"2,Руды и инструменты",
|
||||
"3,Молот",
|
||||
"3,Гравийное сито",
|
||||
"3,Хоппер",
|
||||
"3,Просеивание гравия и хоппер",
|
||||
"3,Меридий",
|
||||
},
|
||||
texts = {
|
||||
"TA1 - про добычу необходимейших руд и изготовление древесного угля простейшими инструментами и оборудованием\\, чтобы ТА2 машины можно было построить и запустить.\n"..
|
||||
"\n"..
|
||||
"Конечно\\, для Эпохи железа потребуется также железо и не только сталь\\, как в ванильной \"Minetest Game\". В результате\\, некоторые рецепты были изменены, и теперь сперва нужно произвести железо, а сталь - позже.\n"..
|
||||
"\n"..
|
||||
"Долговечность инструментов зависит от эпохи и поэтому не соответствует оригинальной игре Майнтест.\n"..
|
||||
"Долговечность / прочность топора\\, например:\n"..
|
||||
"\n"..
|
||||
" - Бронза: 20\n"..
|
||||
" - Сталь: 30\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Для изготовления древесного угля потребуется Углевыжигательная Куча. Древесный уголь используется в плавильной печи\\, но также\\, например\\, в TA2 для парового двигателя.\n"..
|
||||
"\n"..
|
||||
"Для жжения угля понадобится:\n"..
|
||||
"\n"..
|
||||
" - блок-поджигатель ('techage:lighter')\n"..
|
||||
" - 26 деревянный блоков досок, составленных в кучу. Тип дерева не важен.\n"..
|
||||
" - Земля для покрытия кучи дерева.\n"..
|
||||
" - Огниво (техническое наименование: 'fire:flint_and_steel') чтобы зажечь блок-поджигатель\n"..
|
||||
"\n"..
|
||||
"Инструкция по строительству (см. также чертёж):\n"..
|
||||
"\n"..
|
||||
" - Соорудите площадку из земли 5х5\n"..
|
||||
" - Поставьте 7 досок вокруг поджигателя но оставьте отверстие для доступа к поджигателю\n"..
|
||||
" - Постройте ещё 2 слоя досок вверх\\, формируя деревянный куб 3х3х3\n"..
|
||||
" - Покройте всё слоем земли, формируя земляной куб 5х5х5\\, но оставьте отверстие для доступа к поджигателю\n"..
|
||||
" - Воспламените поджигатель и немедленно закройте отверстие блоком досок и блоком земли.\n"..
|
||||
" - Если всё сделано верно\\, углесжигательная куча начнёт пускать дым вверх через несколько секунд\n"..
|
||||
" - Вскрывайте кучу только тогда, когда дым исчезнет! (примерно 20 минут)\n"..
|
||||
"\n"..
|
||||
"Теперь можно забрать 9 блоков древесного угля и заполнить Кучу снова.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Плавильная печь понадобится\\, например\\, чтобы выплавлять железо и другие руды в плавильном тигеле. Для разных рецептов требуется разная температура. Чем выше плавильная башня\\, тем горячее пламя. Высота 11 блоков приемлема для всех рецептов\\, однако и потребляет больше всего древесного угля.\n"..
|
||||
"\n"..
|
||||
"Инструкция по строительству (см. также чертёж):\n"..
|
||||
"\n"..
|
||||
" - Соорудите каменную башню (булыжник) с основанием 3х3 высотой 7-11 блоков.\n"..
|
||||
" - Оставьте отверстие внизу с одной стороны.\n"..
|
||||
" - Поместите поджигатель в отверстие.\n"..
|
||||
" - Заполните башню древесным углем до краёв, сбрасывая древесный уголь сверху в шахту.\n"..
|
||||
" - Воспламените поджигатель через отверстие.\n"..
|
||||
" - Установите плавильный тигель наверху башни\n(на один блок выше пламени)\n"..
|
||||
" - Чтобы временно прервать горение\\, закройте отверстие блоком земли\\, например.\n"..
|
||||
"\n"..
|
||||
"У плавильного тигеля есть своё меню рецептов и инвентарь, куда помещать руды.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Мельница используется для перемалывания пшеницы и других зёрен в муку, затем муку испекают в печи для получения хлеба.\n"..
|
||||
"Мельница крутится силой воды. Для этого\\, к мельнице нужно подвести водный поток каналом.\n"..
|
||||
"Поток воды и мельничное колесо можно контролировать шлюзом. Шлюз состоит из шлюзового замка и шлюзового рычага.\n"..
|
||||
"\n"..
|
||||
"Картинка справа (кликните на \"Plan\") иллюстрирует устройство мельницы. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Мельница используется для перемалывания пшеницы и других зёрен в муку, затем муку испекают в печи для получения хлеба. Мельница должна быть соединена с мельничным колесом посредством ТА1 оси. Мощности мельничного колеса хватает только для одной мельницы.\n"..
|
||||
"\n"..
|
||||
"Автоматизировать мельницу можно Железнодорожным хоппером\\, так что мука\\, например\\, будет перевозиться от мельницы до печи для дальнейшей выпечки.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Шлюзовой затвор нужно размещать непосредственно рядом с водоёмом или в потоке, на том же уровне что и поверхность воды.\n"..
|
||||
"Когда шлюзовой затвор открыт\\, вода стекает вниз. Эта вода напирает на мельничное колесо.\\, и крутит мельницу.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 шлюзовой рычаг размещается на шлюзовом затворе. Затвор можно открывать рычагом (правый клик).\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Блок любого типа дерева для строительства мельничного водоканала. Впрочем\\, можно использовать любой другой материал.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Блок любого типа дерева для строительства мельничного водоканала. Этот блок оптимально подходит для соединения.\n"..
|
||||
"со столбами деревянного забора, для строительства опор канала.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 содержит собственные инструменты, такие как молот и гравийное сито\\, но также можно использовать Железнодорожный хоппер.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 молот используется для разбивания/выкапывания камня\\, а также для раздробления булыжника в гравий. Молот доступен в разных исполнениях с разными свойствами: бронза\\, сталь\\, латунь и алмаз.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Руды можно высеивать из гравия через гравийное сито. Для этого\\, кликайте гравием на сито. Просеянный гравий и руды выпадут снизу.\n"..
|
||||
"\n"..
|
||||
"Чтобы не стоять возле сита часами\\, процесс можно автоматизировать хоппером.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Хоппер из мода \"Minecart\" (Вагонетка) задуман для погрузки-разгрузки вагонеток. Хоппер втягивает предметы сверху от себя и выгружает направо от себя. Так\\, располагая хоппер\\, обращайте внимание на направление выгрузки.\n"..
|
||||
"\n"..
|
||||
"Хоппер также может вытягивать предметы из коробок (сундуков)\\, при условии что коробка расположена рядом или над хоппером.\n"..
|
||||
"\n"..
|
||||
"Хоппер также может помещать предметы в коробки, при условии что коробка расположена рядом с хоппером.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"С помощью двух коробок\\, двух хопперов и гравийного сита\\, процесс просеивания может быть автоматизирован. Чертёж справа иллюстрирует механизм.\n"..
|
||||
"\n"..
|
||||
"Убедитесь, что коробки \"chest_locked\"\\ (защищённые), иначе кто-нибудь похитит ценные руды из верхней коробки.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"TA1 отркрывает собственный сплав - меридий. Меридиевые слитки изготавливаются в плавильном тигеле из стали и месекон кристаллов. Меридий светится в темноте. Меридиевые инструменты тоже светятся, становясь хорошей поддержкой в подземных раскопках.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta1",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta1_sluice",
|
||||
"ta1_sluice_handle",
|
||||
"ta1_board1",
|
||||
"ta1_board2",
|
||||
"ta1_gravelsieve",
|
||||
"hammer",
|
||||
"ta1_gravelsieve",
|
||||
"ta1_hopper",
|
||||
"",
|
||||
"meridium",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"coalpile",
|
||||
"coalburner",
|
||||
"watermill1",
|
||||
"watermill2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"hoppersieve",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,TA1: Idade do Ferro",
|
||||
"2,Pilha de Carvão (queimador de carvão)",
|
||||
"2,Forno de Fundição",
|
||||
"2,Moinho d'Água",
|
||||
"3,Moinho d'Água TA1",
|
||||
"3,Comporta TA1",
|
||||
"3,Alavanca de Comporta TA1",
|
||||
"3,Placa de Madeira de Maçã TA1",
|
||||
"3,Placa de Curso d'Água de Maçã TA1",
|
||||
"1,Minérios e Ferramentas",
|
||||
"2,Martelo",
|
||||
"2,Peneira de Cascalho(Sieve)",
|
||||
"2,Funil (Minecart Hopper)",
|
||||
"2,Peneirando sete cascalhos com Funil",
|
||||
},
|
||||
texts = {
|
||||
"TA1 trata da extração de minérios suficientes e da produção de carvão com ferramentas e equipamentos simples\\, para que as máquinas TA2 possam ser fabricadas e operadas.\n"..
|
||||
"\n"..
|
||||
"É claro que\\, para uma Idade do Ferro\\, deve haver ferro e não apenas aço\\, como em \"Minetest Game\". Como resultado\\, algumas receitas foram alteradas para que o ferro precise ser produzido primeiro e\\, posteriormente\\, o aço.\n"..
|
||||
"\n"..
|
||||
"A durabilidade das ferramentas é baseada nas eras e\\, portanto\\, não corresponde ao jogo original do Minetest.\n"..
|
||||
"A durabilidade/dureza de um machado\\, por exemplo:\n"..
|
||||
"\n"..
|
||||
" - Bronze: 20\n"..
|
||||
" - Aço: 30\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Você precisa da Pilha de Carvão para fazer carvão. O carvão é necessário para a fundição\\, mas também\\, por exemplo\\, em TA2 para a máquina a vapor.\n"..
|
||||
"\n"..
|
||||
"Para o queimador de carvão\\, você precisa de:\n"..
|
||||
"\n"..
|
||||
" - Um bloco de acendedor ('techage:lighter')\n"..
|
||||
" - 26 blocos de madeira empilhados para formar um monte de madeira. O tipo de madeira é irrelevante.\n"..
|
||||
" - Terra para cobrir o monte de madeira\n"..
|
||||
" - Pedra lascada e Ferro (nome técnico: 'fire:flint_and_steel') para acender o bloco de acendedor\n"..
|
||||
"\n"..
|
||||
"Instruções de construção (veja também o plano):\n"..
|
||||
"\n"..
|
||||
" - Construa uma área de 5x5 de terra\n"..
|
||||
" - Coloque 7 blocos de madeira ao redor do acendedor\\, mas deixe um buraco para o acendedor\n"..
|
||||
" - Construa mais 2 camadas de madeira em cima\\, formando um cubo de madeira 3x3x3\n"..
|
||||
" - Cubra tudo com uma camada de terra formando um cubo de 5x5x5\\, mas mantenha o buraco para o acendedor aberto\n"..
|
||||
" - Acenda utilizando o isqueiro e feche imediatamente o buraco com um bloco de madeira e terra\n"..
|
||||
" - Se você fez tudo corretamente\\, o queimador de carvão começará a soltar fumaça após alguns segundos\n"..
|
||||
" - Só abra o queimador de carvão quando a fumaça tiver desaparecido (aproximadamente 20 minutos)\n"..
|
||||
" - Então você pode remover os 9 blocos de carvão e reabastecer a Pilha de Carvão.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Você precisa do forno de fundição\\, por exemplo\\, para fundir ferro e outros minérios no Vaso de fundição(cadinho). Existem receitas diferentes que requerem diferentes temperaturas. Quanto mais alto a torre de fusão\\, mais quente é a chama. Uma altura de 11 blocos acima da placa base é para todas as receitas\\, mas um queimador com essa altura também requer mais carvão.\n"..
|
||||
"\n"..
|
||||
"Instruções de construção (veja também o plano):\n"..
|
||||
"\n"..
|
||||
" - Construa uma torre de pedregulho (cobble) com uma base de 3x3 (7-11 blocos de altura)\n"..
|
||||
" - Deixe um buraco aberto de um lado na parte inferior\n"..
|
||||
" - Coloque um acendedor nele\n"..
|
||||
" - Encha a torre até a borda com carvão despejando o carvão no buraco de cima para baixo\n"..
|
||||
" - Acenda o acendedor através do buraco\n"..
|
||||
" - Coloque o Vaso de fundição(cadinho) no topo da torre diretamente na chama\\, um bloco acima da borda da torre\n"..
|
||||
" - Para parar o queimador\\, feche temporariamente o buraco com um bloco de terra\\, por exemplo.\n"..
|
||||
" - O Vaso de fundição(cadinho) tem seu próprio menu de receitas e um inventário onde você precisa colocar os minérios.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O moinho d'água pode ser usado para moer trigo e outros grãos para fazer farinha e depois assá-los no forno para fazer pão.\n"..
|
||||
"O moinho é alimentado por energia hidráulica. Para isso\\, um curso de água deve ser conduzido até a roda do moinho através de um canal.\n"..
|
||||
"O fluxo de água e\\, portanto\\, a roda do moinho\\, podem ser controlados por meio de uma comporta. A comporta é composta pelo bloqueio de comporta e pela alavanca de comporta.\n"..
|
||||
"\n"..
|
||||
"A imagem à direita (clique em \"Plano\") mostra a estrutura do moinho d'água.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O moinho d'água pode ser usado para moer trigo e outros grãos para fazer farinha e depois assá-los no forno para fazer pão. O moinho deve ser conectado à roda do moinho com um eixo TA1. A potência da roda do moinho é apenas suficiente para um moinho.\n"..
|
||||
"\n"..
|
||||
"O moinho pode ser automatizado com a ajuda de um Funil(Minecart Hopper)\\, para que a farinha\\, por exemplo\\, seja transportada diretamente do moinho para um forno para assar pão.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"A válvula de comporta deve ser colocada diretamente ao lado de um lago ou em um riacho na mesma altura que a superfície da água.\n"..
|
||||
"Quando a comporta é aberta\\, a água flui através do canal. Essa água deve ser conduzida até a roda do moinho\\, onde movimenta o moinho.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"A alavanca de comporta TA1 deve ser colocada na comporta. A comporta pode ser aberta com a ajuda da alavanca de comporta (clique com o botão direito).\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Podem ser usados bloco de diferentes tipos de madeira para construir o canal do curso d'água. No entanto\\, qualquer outro material também pode ser usado.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Podem ser utilizados blocos em diferentes tipos de madeira para construir o canal do curso d'água. Este bloco é especialmente adequado em conexão com postes da cerca de madeira para construir um suporte do canal.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"O TA1 possui suas próprias ferramentas\\, como martelo e peneira de cascalho\\, mas o Funil(Minecart Hopper) também pode ser utilizado.\n"..
|
||||
"\n",
|
||||
"O martelo TA1 pode ser utilizado para bater/escavar pedra em uma mina\\, mas também para quebrar pedregulho(cobble) em cascalho(gravel). O martelo está disponível em diferentes versões\\, cada uma com propriedades distintas: bronze\\, aço\\, latão e diamante.\n"..
|
||||
"\n",
|
||||
"Minérios podem ser peneirados do cascalho com a peneira de cascalho. Para fazer isso\\, clique na peneira com o cascalho. O cascalho peneirado e os minérios caem abaixo.\n"..
|
||||
"\n"..
|
||||
"Para não ficar horas na peneira\\, é possível automatizar o processo com o Funil(Minecart Hopper).\n"..
|
||||
"\n",
|
||||
"O funil do mod \"Minecart Hopper\" é utilizado principalmente para carregar e descarregar carrinhos de mineração. Ele suga itens de cima e os passa para a direita. Portanto\\, ao posicionar o funil\\, preste atenção na direção de dispensa.\n"..
|
||||
"\n"..
|
||||
"O funil também pode puxar itens de baús\\, desde que a caixa esteja ao lado ou em cima do funil.\n"..
|
||||
"\n"..
|
||||
"O funil também pode colocar itens em baús se a caixa estiver ao lado do funil.\n"..
|
||||
"\n",
|
||||
"Com a ajuda de dois baús\\, dois funis e uma peneira de cascalho\\, o processo de peneiração pode ser automatizado. O plano à direita mostra a estrutura.\n"..
|
||||
"\n"..
|
||||
"Certifique-se de que os baús são protegidos\\, caso contrário\\, alguém pode roubar os minérios valiosos do baú abaixo.\n"..
|
||||
"\n"..
|
||||
"Meridium\n"..
|
||||
"O TA1 possui sua própria liga metálica\\, o Meridium. Lingotes de meridium podem ser feitos com a caldeira a carvão\\, utilizando aço e cristais de mesecons. O meridium brilha no escuro. Ferramentas feitas de meridium também emitem luz\\, sendo\\, portanto\\, muito úteis na mineração subterrânea.\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta1",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta1_sluice",
|
||||
"ta1_sluice_handle",
|
||||
"ta1_board1",
|
||||
"ta1_board2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"coalpile",
|
||||
"coalburner",
|
||||
"watermill1",
|
||||
"watermill2",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
@ -1,308 +0,0 @@
|
||||
return {
|
||||
titles = {
|
||||
"1,TA2: Dampfzeitalter",
|
||||
"2,Dampfmaschine",
|
||||
"3,TA2 Feuerbox / Firebox",
|
||||
"3,TA2 Boiler",
|
||||
"3,TA2 Zylinder /Cylinder",
|
||||
"3,TA2 Schwungrad / Flywheel",
|
||||
"3,TA2 Dampfleitungen / Steam Pipe",
|
||||
"3,TA2 Antriebsachsen / TA2 Drive Axle",
|
||||
"3,TA2 Stromgenerator / TA2 Power Generator",
|
||||
"2,TA2 Energiespeicher",
|
||||
"3,TA2 Seilwinde / TA2 Winch",
|
||||
"3,TA2 Gewichtekiste / TA2 Weight Chest",
|
||||
"3,TA2 Kupplung / TA2 Clutch",
|
||||
"2,Items schieben und sortieren",
|
||||
"3,Röhren / TechAge Tube",
|
||||
"3,Röhren Konzentrator / Tube Concentrator",
|
||||
"3,TA2 Schieber / Pusher",
|
||||
"3,TA2 Verteiler / Distributor",
|
||||
"2,Kieswaschanlage",
|
||||
"3,TA2 Kiesspüler / Gravel Rinser",
|
||||
"2,Stein brechen\\, mahlen und sieben",
|
||||
"3,TA2 Steinbrecher / Quarry",
|
||||
"3,TA2 Mühle / Grinder",
|
||||
"3,TA2 Kiessieb / Gravel Sieve",
|
||||
"2,Items produzieren",
|
||||
"3,TA2 Autocrafter",
|
||||
"3,TA2 Elektronikfabrik / Electronic Fab",
|
||||
"2,Sonstige Blöcke",
|
||||
"3,TA2 Flüssigkeitensammler / Liquid Sampler",
|
||||
"3,TA2 Gesicherte Kiste / Protected Chest",
|
||||
"3,Techage Forceload Block",
|
||||
},
|
||||
texts = {
|
||||
"In TA2 geht es darum\\, erste Maschinen zur Verarbeitung von Erzen zu bauen und zu betreiben. Einige Maschinen müssen dazu über Antriebsachsen angetrieben werden. Dazu musst du eine Dampfmaschine bauen und diese mit Kohle oder Holzkohle anheizen.\n"..
|
||||
"\n"..
|
||||
"In TA2 steht auch ein Kiesspüler zur Verfügung\\, mit dem seltene Erze wie Usmium Nuggets ausgewaschen werden können. Diese Nuggets wirst du später für weitere Rezepte brauchen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Dampfmaschine besteht aus mehreren Blöcken und muss wie im Plan rechts abgebildet\\, zusammen gebaut werden. Dazu werden die Blöcke TA2 Feuerbox\\, TA2 Boiler oben\\, TA2 Boiler unten\\, TA2 Zylinder\\, TA2 Schwungrad und Dampfleitungen benötigt.\n"..
|
||||
"\n"..
|
||||
"Zusätzlich werden Antriebsachsen sowie Getriebeblöcke für Richtungswechsel benötigt. Das Schwungrad muss über die Antriebsachsen mit allen Maschinen verbunden werden\\, die angetrieben werden müssen.\n"..
|
||||
"\n"..
|
||||
"Bei allen Blöcken beim Setzen immer auch die Ausrichtung achten:\n"..
|
||||
"\n"..
|
||||
" - Zylinder links\\, Schwungrad rechts daneben\n"..
|
||||
" - Dampfleitungen anschließen\\, wo ein entsprechendes Loch ist\n"..
|
||||
" - Antriebsachse beim Schwungrad nur rechts\n"..
|
||||
" - bei allen Maschinen kann die Antriebsachse an allen Seiten angeschlossen werden\\, welche nicht durch andere Funktionen belegt wird\\, wie bspw. die IN und OUT Löcher bei Mühle und Sieb.\n"..
|
||||
"\n"..
|
||||
"Der Boiler muss mit Wasser gefüllt werden. Dazu bis zu 10 Eimer Wasser in den Boiler füllen.\n"..
|
||||
"Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden.\n"..
|
||||
"Wenn das Wasser heiß ist (Temperaturanzeige ganz oben)\\, kann die Dampfmaschine am Schwungrad gestartet werden.\n"..
|
||||
"\n"..
|
||||
"Die Dampfmaschine leistet 25 ku und kann damit mehrere Maschinen gleichzeitig antreiben.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Teil der Dampfmaschine. \n"..
|
||||
"\n"..
|
||||
"Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden. Die Brenndauer ist abhängig von der Leistung\\, die von der Dampfmaschine angefordert wird. Unter Volllast brennt Kohle 32 s und Holzkohle 96 s.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Teil der Dampfmaschine. Muss mit Wasser gefüllt werden. Dies erfolgt durch Klicken mit einem Wassereimer auf den Boiler. Wenn kein Wasser mehr vorhanden ist oder die Temperatur zu weit absinkt\\, schaltet sich die Dampfmaschine ab. Bei der Dampfmaschine geht bei jedem Kolbenhub etwas Wasser als Dampf verloren\\, daher muss regelmäßig Wasser nachgefüllt werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Teil der Dampfmaschine.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Antriebsteil der Dampfmaschine. Das Schwungrad muss über Antriebsachsen mit den Maschinen verbunden werden. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Teil der Dampfmaschine. Der Boiler muss mit dem Zylinder über die Dampfleitungen (steam pipes) verbunden werden. Die Dampfleitung besitzt keine Abzweigungen\\, die maximale Länge beträgt 12 m (Blöcke).\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen Maschinen. Die maximale Länge einer Antriebsachse beträgt 10 Blöcke. Über Getriebeblöcke können auch größere Strecken überbrückt\\, sowie Abzweigungen und Richtungswechsel realisiert werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Um Lampen oder andere Stromverbraucher an einer Dampfmaschine betreiben zu können\\, wird der TA2 Stromgenerator benötigt. Der TA2 Stromgenerator muss auf einer Seite mit Antriebsachsen verbunden werden und liefert dann auf der anderen Seite elektrischen Strom.\n"..
|
||||
"\n"..
|
||||
"Wird der Stromgenerator nicht mit ausreichend Kraft versorgt\\, geht er in einen Fehlerzustand und muss über einen Rechtsklick wieder aktiviert werden.\n"..
|
||||
"\n"..
|
||||
"Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundär max. 24 ku als Strom wieder ab. Er verbraucht also ein ku für die Umwandlung.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Bei größeren Anlagen mit mehreren Dampfmaschinen oder vielen angetriebenen Maschinen empfiehlt sich ein Energiespeicher. Der Energiespeicher bei TA2 arbeitet mit Lageenergie. Dazu wird Balast (Steine\\, Kies) in einer Kiste mit Hilfe einer Seilwinde in die Höhe gezogen. Ist überschüssige Energie im Achsen-Netzwerk vorhanden\\, so wird die Kiste nach oben gezogen. Wird kurzfristig mehr Energie benötigt\\, als die Dampfmaschine liefern kann\\, so gibt der Energiespeicher die gespeicherte Energie wieder ab\\, und die Balast-Kiste bewegt sich wieder nach unten.\n"..
|
||||
"\n"..
|
||||
"Der Energiespeicher besteht aus mehreren Blöcken und muss wie im Plan rechts abgebildet\\, zusammen gebaut werden.\n"..
|
||||
"\n"..
|
||||
"Um die maximale Speicherkapazität zu erreichen\\, muss die Kiste mit Gewichten komplett gefüllt\\, und der Mast inklusive der zwei Getriebeblöcke 12 Blöcke hoch sein. Kleinere Aufbauten sind aber auch möglich.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Seilwinde muss mit einem Getriebeblock verbunden werden und kann so überschüssige Energie aufnehmen und damit eine Gewichtekiste nach oben ziehen. Achte beim Aufbau der Seilwinde darauf\\, dass der Pfeil auf der Blockoberseite zum Getriebeblock zeigt. Die maximale Seillänge beträgt 10 Blöcke.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Diese Kiste muss mit bis zu 10 Blöcken Abstand unter die Seilwinde gesetzt und mit Pflastersteinen Kies oder Sand gefüllt werden. Ist das Mindestgewicht von einem Stack (99+ Items) erreicht und überschüssige Energie vorhanden\\, wird die Kiste automatisch über eine Seil mit der Seilwinde verbunden und in die Höhe gezogen.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit der Kupplung können Achsen und Maschinen vom Energiespeicher getrennt werden. Damit kommen die Achsen nach der Kupplung zum Stillstand und Maschinenanlagen können umgebaut werden. Achte beim Aufbau der Kupplung darauf\\, dass der Pfeil auf der Blockoberseite zum Energiespeicher zeigt. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Um Gegenstände (Items) von einer Verarbeitungsstation zur nächsten weiter zu transportieren\\, werden Schieber und Röhren verwendet. Siehe Plan.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Zwei Maschinen können mit Hilfe eines Schiebers und einer Röhre (tube) verbunden werden. Röhren besitzen keine Abzweigungen. Die maximale Länge beträgt 200 m (Blöcke).\n"..
|
||||
"\n"..
|
||||
"Röhren können alternativ mit Hilfe der Shift-Taste platziert werden. Dies erlaubt bspw. Röhren parallel zu verlegen\\, ohne dass diese sich unbeabsichtigt verbinden.\n"..
|
||||
"\n"..
|
||||
"Die Transportkapazität einer Röhre ist unbegrenzt und nur durch die Schieber begrenzt.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Über den Konzentrator können mehrere Röhren zu einer Röhre zusammengeführt werden. Die Richtung\\, in der alle Items weitergegeben werden\\, ist mit einem Pfeil markiert.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Ein Schieber ist in der Lage\\, Items aus Kisten oder Maschinen zu ziehen und in andere Kisten oder Maschinen zu schieben. Oder anders gesagt: Zwischen zwei Blöcken mit Inventar muss ein und genau ein Schieber sein. Mehrere Schieber in Reihe sind nicht möglich.\n"..
|
||||
"In die Gegenrichtung ist ein Schieber für Items aber durchlässig\\, so dass eine Kiste über eine Röhre gefüllt und ebenso geleert werden kann. \n"..
|
||||
"\n"..
|
||||
"Ein Schieber geht in den Zustand \"standby\"\\, wenn der keine Items zum Schieben hat. Ist der Ausgang blockiert oder das Inventory des Empfängers voll\\, so geht der Schieber in den Zustand \"blocked\". Aus beiden Zuständen kommt der Schieber nach einigen Sekunden selbsttätig wieder raus\\, sofern sich die Situation geändert hat.\n"..
|
||||
"\n"..
|
||||
"Der Verarbeitungsleistung eines TA2 Schiebers beträgt 2 Items alle 2 s.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der Verteiler ist in der Lage\\, die Items aus seinem Inventar sortiert in bis zu vier Richtungen weiter zu transportieren. Dazu muss der Verteiler entsprechend konfiguriert werden. \n"..
|
||||
"\n"..
|
||||
"Der Verteiler besitzt dazu ein Menü mit 4 Filter mit unterschiedlichen Farben\\, entsprechend den 4 Ausgängen. Soll ein Ausgang genutzt werden\\, so muss der entsprechende Filter über die \"on\" Checkbox aktiviert werden. Alle Items\\, die für diesen Filter konfiguriert sind\\, werden über den zugeordneten Ausgang ausgegeben. Wird ein Filter aktiviert\\, ohne das Items konfiguriert werden\\, so sprechen wir hier von einem \"nicht-konfigurierten\"\\, offenen Ausgang.\n"..
|
||||
"\n"..
|
||||
"*Achtung: Der Verteiler ist an seinen Ausgängen gleichzeitig ein Schieber. Daher niemals die Gegenstände mit einem Schieber aus dem Verteiler ziehen!*\n"..
|
||||
"\n"..
|
||||
"Für einen nicht-konfigurierten Ausgang gibt es zwei Betriebsarten:\n"..
|
||||
"\n"..
|
||||
"1) Alle Items ausgeben\\, die an keine anderen Ausgängen ausgegeben werden können\\, auch wenn diese blockiert sind.\n"..
|
||||
"\n"..
|
||||
"2) Nur die Items ausgeben\\, die für keinen anderen Filter konfiguriert wurden.\n"..
|
||||
"\n"..
|
||||
"Im ersten Fall werden immer alle Items weitergeleitet und der Verteiler läuft nicht voll. Im zweiten Fall werden Items zurückgehalten und der Verteiler kann voll laufen und in der Folge blockieren.\n"..
|
||||
"\n"..
|
||||
"Einstellbar ist die Betriebsart über die \"blockiere\" Checkbox.\n"..
|
||||
"\n"..
|
||||
"Der Verarbeitungsleistung eines TA2 Verteilers beträgt 4 Items alle 2 s\\, wobei der Verteiler dabei versucht\\, die 4 Items auf die offenen Ausgänge zu verteilen.\n"..
|
||||
"\n"..
|
||||
"Wird dasselbe Item in einem Filter mehrfach hinterlegt\\, so beeinflusst dies das langfristige Verteilungsverhältnis entsprechend.\n"..
|
||||
"\n"..
|
||||
"Bitte beachte\\, dass die Verteilung ein probabilistischer Vorgang ist\\, d.h. die Verhältnisse werden nicht exakt\\, sondern nur langfristig eingehalten.\n"..
|
||||
"\n"..
|
||||
"In den Filtern beträgt die maximale Stackgröße 12\\; insgesamt können höchstens 36 Items konfiguriert werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Kieswaschanlage ist eine komplexere Maschine mit dem Ziel\\, Usmium Nuggets aus gesiebtem Kies auszuwaschen. Für den Aufbau wird ein TA2 Kiesspüler mit Achsenantrieb\\, ein Trichter\\, eine Kiste\\, sowie fließendes Wasser benötigt. \n"..
|
||||
"\n"..
|
||||
"Aufbau von links nach rechts (siehe auch Plan):\n"..
|
||||
"\n"..
|
||||
" - Ein Erdblock\\, darauf die Wasserquelle\\, umgeben auf 3 Seiten von bspw. Glasblöcken\n"..
|
||||
" - daneben den Kiesspüler\\, ggf. mit Röhrenanschlüssen für den Kies An- und Abtransport\n"..
|
||||
" - dann den Trichter mit Kiste\n"..
|
||||
"\n"..
|
||||
"Das Ganze umgeben von weiteren Glasblöcken\\, so dass das Wasser über den Kiesspüler und den Trichter fließt und ausgespülten Nuggets vom Trichter wieder eingesammelt werden können.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der Kiesspüler ist in der Lage\\, aus bereits gesiebtem Kies die Erze Usmium und Kupfer auszuspülen\\, sofern dieser von Wasser überspült wird.\n"..
|
||||
"\n"..
|
||||
"Ob der Kiesspüler korrekt arbeitet\\, kann mit Hilfe von Stöcken (sticks) getestet werden\\, wenn diese in das Inventar des Kiesspülers getan werden. Diese müssen einzeln ausgespült und vom Trichter eingefangen werden.\n"..
|
||||
"\n"..
|
||||
"Die Verarbeitungsleistung ist ein Kies Item alle 2 s. Der Kiesspüler benötigt 3 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Das Brechen\\, Mahlen und Siebe von Gestein dient zur Gewinnung von Erzen. Gesiebtes Kies kann aber auch anderweitig genutzt werden. Steinbrecher\\, Mühle und Sieb müssen angetrieben und damit in der Nähe einer Dampfmaschine aufgebaut werden.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Der Steinbrecher dient zum Abbau von Steinen und anderen Materialien aus dem Untergrund. Der Steinbrecher gräbt ein 5x5 Blöcke großes Loch. Die Tiefe ist einstellbar.\n"..
|
||||
"Die Verarbeitungsleistung ist ein Block alle 4 s. Der Steinbrecher benötigt 10 ku Energie. Die maximale Tiefe beträgt 20 Meter. Für größere Tiefen siehe TA3/TA4.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Mühle ist in der Lage\\, verschiedenes Gestein\\, aber auch Holz und andere Items zu mahlen.\n"..
|
||||
"Die Verarbeitungsleistung ist ein Item alle 4 s. Die Mühle benötigt 4 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Das Kiessieb ist in der Lage\\, Kies zu sieben um Erze zu gewinnen. Als Ergebnis erhält man teilweise \"gesiebtes Kies\"\\, was nicht wieder gesiebt werden kann.\n"..
|
||||
"Die Verarbeitungsleistung ist ein Item alle 4 s. Das Kiessieb benötigt 3 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Mit TA2 Maschinen können nicht nur Erze gewonnen\\, sondern auch Gegenstände hergestellt werden.\n"..
|
||||
"\n",
|
||||
"Der Autocrafter dient zur automatischen Herstellung von Waren. Alles was der Spieler über das \"Crafting Grid\" herstellen kann\\, kann auch durch den Autocrafter erledigt werden. Dazu müssen im Menü des Autocrafters das Rezept eingegeben und die notwendigen Zutaten hinzugefügt werden.\n"..
|
||||
"\n"..
|
||||
"Zutaten und hergestellte Waren können über Röhren und Schieber in und aus dem Block transportiert werden.\n"..
|
||||
"\n"..
|
||||
"Die Verarbeitungsleistung ist ein Item alle 4 s. Der Autocrafter benötigt 4 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die Elektronikfabrik ist eine Spezialmaschine und nur für die Herstellung der Vakuumröhren nutzbar. Vakuumröhren werden für TA3 Maschinen und Blöcke benötigt.\n"..
|
||||
"\n"..
|
||||
"Die Verarbeitungsleistung ist eine Vakuumröhre alle 6 s. Die Elektronikfabrik benötigt 8 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"",
|
||||
"Für manche Rezepte wird Wasser benötigt. Damit auch diese Rezepte automatisiert mit dem Autocrafter bearbeitet werden können\\, muss Wasser in Eimern bereitgestellt werden. Hierzu dient der Flüssigkeitensammler. Er benötigt leere Eimer und muss ins Wasser gestellt werden.\n"..
|
||||
"\n"..
|
||||
"Die Verarbeitungsleistung ist ein Wassereimer alle 8 s. Der Flüssigkeitensammler benötigt 3 ku Energie.\n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Die gesicherte Kiste kann nur von den Spielern genutzt werden\\, die an diesem Ort auch bauen können\\, also Protection Rechte besitzen. Es spielt dabei keine Rolle\\, wer die Kiste setzt. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
"Minetest teilt die Karte in sogenannte Map-Blocks ein. Das sind Würfel mit 16x16x16 Blöcke Kantenlänge. So ein Map-Block wird vom Server immer komplett geladen\\, aber es werden nur die Blöcke um einen Spieler herum geladen (ca. 2-3 Blöcke in alle Richtungen). In Sichtrichtung des Spielers sind es auch mehr Map-Blöcke. Nur dieser Teil der Welt ist aktiv und nur hier wachsen Pflanzen und Bäume bzw. laufen die Maschinen.\n"..
|
||||
"\n"..
|
||||
"Mit einem Forceload-Block kannst du erzwingen\\, dass der Map-Block\\, in dem der Forceload Block steht\\, immer geladen bleibt\\, solange du auf dem Server bist. Wenn alle deine Farmen und Maschinen mit Forceload Blöcken abgedeckt sind\\, ist immer alles am Laufen.\n"..
|
||||
"\n"..
|
||||
"Die Map-Blöcke mit ihren Koordinaten sind vordefiniert\\, also bspw. (0\\,0\\,0) bis (15\\,15\\,15)\\, oder (16\\,16\\,16) bis (31\\,31\\,31).\n"..
|
||||
"Man kann einen Forceload-Block innerhalb eines Map-Blockes verschieben wie man will\\, die Position des Map-Blocks bleibt dabei unverändert. \n"..
|
||||
"\n"..
|
||||
"\n"..
|
||||
"\n",
|
||||
},
|
||||
images = {
|
||||
"techage_ta2",
|
||||
"",
|
||||
"ta2_firebox",
|
||||
"ta2_boiler",
|
||||
"ta2_cylinder",
|
||||
"ta2_flywheel",
|
||||
"ta2_steampipe",
|
||||
"ta2_driveaxle",
|
||||
"ta2_generator",
|
||||
"",
|
||||
"ta2_winch",
|
||||
"ta2_weight_chest",
|
||||
"techage:ta2_clutch_off",
|
||||
"",
|
||||
"tube",
|
||||
"concentrator",
|
||||
"ta2_pusher",
|
||||
"ta2_distributor",
|
||||
"",
|
||||
"ta2_rinser",
|
||||
"ta2_grinder",
|
||||
"ta2_quarry",
|
||||
"ta2_grinder",
|
||||
"ta2_gravelsieve",
|
||||
"",
|
||||
"ta2_autocrafter",
|
||||
"ta2_electronicfab",
|
||||
"",
|
||||
"ta2_liquidsampler",
|
||||
"ta2_chest",
|
||||
"ta2_forceload",
|
||||
},
|
||||
plans = {
|
||||
"",
|
||||
"steamengine",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ta2_storage",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"itemtransport",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"gravelrinser",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user