diff --git a/.luacheckrc b/.luacheckrc index 52b25132..3c7ec693 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -8,6 +8,10 @@ read_globals = { "vector", "VoxelManip", "VoxelArea", "PseudoRandom", "ItemStack", + "Settings", + "unpack", + -- Silence "accessing undefined field copy of global table". + table = { fields = { "copy" } } } -- Overwrites minetest.handle_node_drops diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..48f0b8d1 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,519 @@ +License of media (textures and sounds) +-------------------------------------- +Copyright (C) 2010-2012 celeron55, Perttu Ahola +See README.txt in each mod directory for information about other authors. + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +http://creativecommons.org/licenses/by-sa/3.0/ + +License of menu/header.png +Copyright (C) 2015 paramat CC BY-SA 3.0 + + +License of source code +---------------------- +Copyright (C) 2010-2012 celeron55, Perttu Ahola +See README.txt in each mod directory for information about other authors. + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/README.txt b/README.txt index b59b7f94..97ad70ab 100644 --- a/README.txt +++ b/README.txt @@ -22,32 +22,7 @@ When stable releases are made, Minetest Game is packaged and made available in and in case the repository has grown too much, it may be reset. In that sense, this is not a "real" git repository. (Package maintainers please note!) -License of source code ----------------------- -Copyright (C) 2010-2012 celeron55, Perttu Ahola -See README.txt in each mod directory for information about other authors. +Licensing +--------- -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -License of media (textures and sounds) --------------------------------------- -Copyright (C) 2010-2012 celeron55, Perttu Ahola -See README.txt in each mod directory for information about other authors. - -Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) -http://creativecommons.org/licenses/by-sa/3.0/ - -License of menu/header.png -Copyright (C) 2015 paramat CC BY-SA 3.0 +See LICENSE.txt diff --git a/game_api.txt b/game_api.txt index 38718c36..887f394e 100644 --- a/game_api.txt +++ b/game_api.txt @@ -78,6 +78,12 @@ For example, is used to show all tools. Name is used in the sfinv page name, title is the human readable title. +`is_enabled_for` is used to check whether a player is in creative mode: + + creative.is_enabled_for(name) + +Override this to allow per-player game modes. + The contents of `creative.formspec_add` is appended to every creative inventory page. Mods can use it to add additional formspec elements onto the default creative inventory formspec to be drawn after each update. @@ -276,18 +282,6 @@ Give Initial Stuff API ^ str is a comma separated list of initial stuff ^ Adds items to the list of items to be given -Nyancat API ------------ - -`nyancat.place(pos, facedir, length)` - -^ Place a cat at `pos` facing `facedir` with tail length `length` - Only accepts facedir 0-3, if facedir > 3 then it will be interpreted as facedir = 0 - -`nyancat.generate(minp, maxp, seed)` - -^ Called by `minetest.register_on_generated`. To disable nyancat generation, - you can redefine nyancat.generate() to be an empty function TNT API ---------- @@ -318,8 +312,10 @@ TNT API `tnt.burn(position, [nodename])` -^ Ignite TNT at position, nodename isn't required unless already known. - +^ Ignite node at position, triggering its `on_ignite` callback (see fire mod). +If no such callback exists, fallback to turn tnt group nodes to their +"_burning" variant. + nodename isn't required unless already known. To make dropping items from node inventories easier, you can use the following helper function from 'default': @@ -406,18 +402,28 @@ Sfinv API ### sfinv Methods -* sfinv.set_player_inventory_formspec(player, context) - builds page formspec - and calls set_inventory_formspec(). - If context is nil, it is either found or created. -* sfinv.get_formspec(player, context) - builds current page's formspec -* sfinv.get_nav_fs(player, context, nav, current_idx) - see above +**Pages** + +* sfinv.set_page(player, pagename) - changes the page * sfinv.get_homepage_name(player) - get the page name of the first page to show to a player -* sfinv.make_formspec(player, context, content, show_inv, size) - adds a theme to a formspec - * show_inv, defaults to false. Whether to show the player's main inventory - * size, defaults to `size[8,8.6]` if not specified * sfinv.register_page(name, def) - register a page, see section below * sfinv.override_page(name, def) - overrides fields of an page registered with register_page. * Note: Page must already be defined, (opt)depend on the mod defining it. +* sfinv.set_player_inventory_formspec(player) - (re)builds page formspec + and calls set_inventory_formspec(). +* sfinv.get_formspec(player, context) - builds current page's formspec + +**Contexts** + +* sfinv.get_or_create_context(player) - gets the player's context +* sfinv.set_context(player, context) + +**Theming** + +* sfinv.make_formspec(player, context, content, show_inv, size) - adds a theme to a formspec + * show_inv, defaults to false. Whether to show the player's main inventory + * size, defaults to `size[8,8.6]` if not specified +* sfinv.get_nav_fs(player, context, nav, current_idx) - creates tabheader or "" ### sfinv Members @@ -642,20 +648,36 @@ default.player_get_animation(player) Leafdecay --------- -To enable leaf decay for a node, add it to the `leafdecay` group. +To enable leaf decay for leaves when a tree is cut down by a player, +register the tree with the default.register_leafdecay(leafdecaydef) +function. -The rating of the group determines how far from a node in the group `tree` -the node can be without decaying. +If `param2` of any registered node is ~= 0, the node will always be +preserved. Thus, if the player places a node of that kind, you will +want to set `param2 = 1` or so. -If `param2` of the node is ~= 0, the node will always be preserved. Thus, if -the player places a node of that kind, you will want to set `param2 = 1` or so. +The function `default.after_place_leaves` can be set as +`after_place_node of a node` to set param2 to 1 if the player places +the node (should not be used for nodes that use param2 otherwise +(e.g. facedir)). -The function `default.after_place_leaves` can be set as `after_place_node of a node` -to set param2 to 1 if the player places the node (should not be used for nodes -that use param2 otherwise (e.g. facedir)). +If the node is in the `leafdecay_drop` group then it will always be +dropped as an item. + +`default.register_leafdecay(leafdecaydef)` + +`leafdecaydef` is a table, with following members: + { + trunks = {"default:tree"}, -- nodes considered trunks + leaves = {"default:leaves", "default:apple"}, + -- nodes considered for removal + radius = 3, -- radius to consider for searching + } + +Note: all the listed nodes in `trunks` have their `on_after_destruct` +callback overridden. All the nodes listed in `leaves` have their +`on_timer` callback overridden. -If the node is in the `leafdecay_drop` group then it will always be dropped as an -item. Dyes ---- @@ -746,14 +768,20 @@ Trees * `default.grow_new_pine_tree(pos)` * Grows a new design pine tree at pos + * `default.grow_new_snowy_pine_tree(pos)` + * Grows a new design snowy pine tree at pos + * `default.grow_new_acacia_tree(pos)` * Grows a new design acacia tree at pos * `default.grow_new_aspen_tree(pos)` * Grows a new design aspen tree at pos - * `default.grow_new_snowy_pine_tree(pos)` - * Grows a new design snowy pine tree at pos + * `default.grow_bush(pos)` + * Grows a bush at pos + + * `default.grow_acacia_bush(pos)` + * Grows an acaia bush at pos Carts ----- diff --git a/minetest.conf.example b/minetest.conf.example index 3f20eb77..9393b1a5 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -27,6 +27,9 @@ # Enable flame sound. #flame_sound = true +# Whether lavacooling should be enabled. +#enable_lavacooling = true + # Whether the stuff in initial_stuff should be given to new players #give_initial_stuff = false #initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,default:torch 99,default:cobble 99 diff --git a/mods/beds/api.lua b/mods/beds/api.lua index 3b2bb0d5..97dde43d 100644 --- a/mods/beds/api.lua +++ b/mods/beds/api.lua @@ -34,7 +34,7 @@ function beds.register_bed(name, def) is_ground_content = false, stack_max = 1, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1}, - sounds = default.node_sound_wood_defaults(), + sounds = def.sounds or default.node_sound_wood_defaults(), node_box = { type = "fixed", fixed = def.nodebox.bottom, @@ -46,6 +46,14 @@ function beds.register_bed(name, def) on_place = function(itemstack, placer, pointed_thing) local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + local pos if minetest.registered_items[minetest.get_node(under).name].buildable_to then pos = under @@ -81,7 +89,8 @@ function beds.register_bed(name, def) minetest.set_node(pos, {name = name .. "_bottom", param2 = dir}) minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then itemstack:take_item() end return itemstack @@ -138,7 +147,7 @@ function beds.register_bed(name, def) is_ground_content = false, pointable = false, groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2}, - sounds = default.node_sound_wood_defaults(), + sounds = def.sounds or default.node_sound_wood_defaults(), drop = name .. "_bottom", node_box = { type = "fixed", diff --git a/mods/beds/functions.lua b/mods/beds/functions.lua index 896844e5..78df9a18 100644 --- a/mods/beds/functions.lua +++ b/mods/beds/functions.lua @@ -1,7 +1,7 @@ local pi = math.pi local player_in_bed = 0 local is_sp = minetest.is_singleplayer() -local enable_respawn = minetest.setting_getbool("enable_bed_respawn") +local enable_respawn = minetest.settings:get_bool("enable_bed_respawn") if enable_respawn == nil then enable_respawn = true end @@ -22,7 +22,7 @@ local function get_look_yaw(pos) end local function is_night_skip_enabled() - local enable_night_skip = minetest.setting_getbool("enable_bed_night_skip") + local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip") if enable_night_skip == nil then enable_night_skip = true end diff --git a/mods/boats/init.lua b/mods/boats/init.lua index 0591ef24..4d8f4673 100644 --- a/mods/boats/init.lua +++ b/mods/boats/init.lua @@ -110,7 +110,8 @@ function boat.on_punch(self, puncher) if not self.driver then self.removed = true local inv = puncher:get_inventory() - if not minetest.setting_getbool("creative_mode") + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(puncher:get_player_name())) or not inv:contains_item("main", "boats:boat") then local leftover = inv:add_item("main", "boats:boat") -- if no room in inventory add a replacement boat to the world @@ -225,6 +226,15 @@ minetest.register_craftitem("boats:boat", { groups = {flammable = 2}, on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + if pointed_thing.type ~= "node" then return itemstack end @@ -235,7 +245,8 @@ minetest.register_craftitem("boats:boat", { boat = minetest.add_entity(pointed_thing.under, "boats:boat") if boat then boat:setyaw(placer:get_look_horizontal()) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then itemstack:take_item() end end diff --git a/mods/bones/init.lua b/mods/bones/init.lua index 9542cab0..9583bc29 100644 --- a/mods/bones/init.lua +++ b/mods/bones/init.lua @@ -21,8 +21,8 @@ local bones_formspec = "listring[current_player;main]" .. default.get_hotbar_bg(0,4.85) -local share_bones_time = tonumber(minetest.setting_get("share_bones_time")) or 1200 -local share_bones_time_early = tonumber(minetest.setting_get("share_bones_time_early")) or share_bones_time / 4 +local share_bones_time = tonumber(minetest.settings:get("share_bones_time")) or 1200 +local share_bones_time_early = tonumber(minetest.settings:get("share_bones_time_early")) or share_bones_time / 4 minetest.register_node("bones:bones", { description = "Bones", @@ -161,13 +161,14 @@ end minetest.register_on_dieplayer(function(player) - local bones_mode = minetest.setting_get("bones_mode") or "bones" + local bones_mode = minetest.settings:get("bones_mode") or "bones" if bones_mode ~= "bones" and bones_mode ~= "drop" and bones_mode ~= "keep" then bones_mode = "bones" end -- return if keep inventory set or in creative mode - if bones_mode == "keep" or minetest.setting_getbool("creative_mode") then + if bones_mode == "keep" or (creative and creative.is_enabled_for + and creative.is_enabled_for(player:get_player_name())) then return end diff --git a/mods/carts/cart_entity.lua b/mods/carts/cart_entity.lua index e8707fb4..a19da648 100644 --- a/mods/carts/cart_entity.lua +++ b/mods/carts/cart_entity.lua @@ -92,7 +92,8 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, end -- Pick up cart local inv = puncher:get_inventory() - if not minetest.setting_getbool("creative_mode") + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(puncher:get_player_name())) or not inv:contains_item("main", "carts:cart") then local leftover = inv:add_item("main", "carts:cart") -- If no room in inventory add a replacement cart to the world @@ -362,6 +363,15 @@ minetest.register_craftitem("carts:cart", { inventory_image = minetest.inventorycube("carts_cart_top.png", "carts_cart_side.png", "carts_cart_side.png"), wield_image = "carts_cart_side.png", on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + if not pointed_thing.type == "node" then return end @@ -376,7 +386,8 @@ minetest.register_craftitem("carts:cart", { minetest.sound_play({name = "default_place_node_metal", gain = 0.5}, {pos = pointed_thing.above}) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then itemstack:take_item() end return itemstack diff --git a/mods/carts/functions.lua b/mods/carts/functions.lua index 285645cb..a4717194 100644 --- a/mods/carts/functions.lua +++ b/mods/carts/functions.lua @@ -181,8 +181,8 @@ function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype) return false end -function carts:register_rail(name, def, railparams) - local def_default = { +function carts:register_rail(name, def_overwrite, railparams) + local def = { drawtype = "raillike", paramtype = "light", sunlight_propagates = true, @@ -194,7 +194,7 @@ function carts:register_rail(name, def, railparams) }, sounds = default.node_sound_metal_defaults() } - for k, v in pairs(def_default) do + for k, v in pairs(def_overwrite) do def[k] = v end if not def.inventory_image then diff --git a/mods/carts/rails.lua b/mods/carts/rails.lua index 5da4ac4d..066779d1 100644 --- a/mods/carts/rails.lua +++ b/mods/carts/rails.lua @@ -10,11 +10,11 @@ carts:register_rail("carts:rail", { }, {}) minetest.register_craft({ - output = "carts:rail 16", + output = "carts:rail 18", recipe = { + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, {"default:steel_ingot", "", "default:steel_ingot"}, - {"default:steel_ingot", "group:stick", "default:steel_ingot"}, - {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, } }) @@ -31,11 +31,11 @@ carts:register_rail("carts:powerrail", { }, {acceleration = 5}) minetest.register_craft({ - output = "carts:powerrail 8", + output = "carts:powerrail 18", recipe = { - {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, - {"default:steel_ingot", "group:stick", "default:steel_ingot"}, - {"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"}, + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, + {"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"}, + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, } }) @@ -50,10 +50,10 @@ carts:register_rail("carts:brakerail", { }, {acceleration = -3}) minetest.register_craft({ - output = "carts:brakerail 8", + output = "carts:brakerail 18", recipe = { + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, - {"default:steel_ingot", "group:stick", "default:steel_ingot"}, - {"default:steel_ingot", "default:coal_lump", "default:steel_ingot"}, + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, } }) diff --git a/mods/carts/textures/carts_cart_front.png b/mods/carts/textures/carts_cart_front.png index b85696f9..38955b25 100644 Binary files a/mods/carts/textures/carts_cart_front.png and b/mods/carts/textures/carts_cart_front.png differ diff --git a/mods/carts/textures/carts_cart_side.png b/mods/carts/textures/carts_cart_side.png index 4362d6b1..f53808c6 100644 Binary files a/mods/carts/textures/carts_cart_side.png and b/mods/carts/textures/carts_cart_side.png differ diff --git a/mods/carts/textures/carts_cart_top.png b/mods/carts/textures/carts_cart_top.png index 5f775ff1..d9a31a9d 100644 Binary files a/mods/carts/textures/carts_cart_top.png and b/mods/carts/textures/carts_cart_top.png differ diff --git a/mods/creative/init.lua b/mods/creative/init.lua index 868b802b..51d6f792 100644 --- a/mods/creative/init.lua +++ b/mods/creative/init.lua @@ -1,6 +1,14 @@ +creative = {} + +local creative_mode_cache = minetest.settings:get_bool("creative_mode") + +function creative.is_enabled_for(name) + return creative_mode_cache +end + dofile(minetest.get_modpath("creative") .. "/inventory.lua") -if minetest.setting_getbool("creative_mode") then +if creative_mode_cache then -- Dig time is modified according to difference (leveldiff) between tool -- 'maxlevel' and node 'level'. Digtime is divided by the larger of -- leveldiff and 1. @@ -28,22 +36,27 @@ if minetest.setting_getbool("creative_mode") then damage_groups = {fleshy = 10}, } }) +end - minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) - return true - end) +-- Unlimited node placement +minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) + return creative.is_enabled_for(placer:get_player_name()) +end) - function minetest.handle_node_drops(pos, drops, digger) - if not digger or not digger:is_player() then - return - end - local inv = digger:get_inventory() - if inv then - for _, item in ipairs(drops) do - item = ItemStack(item):get_name() - if not inv:contains_item("main", item) then - inv:add_item("main", item) - end +-- Don't pick up if the item is already in the inventory +local old_handle_node_drops = minetest.handle_node_drops +function minetest.handle_node_drops(pos, drops, digger) + if not digger or not digger:is_player() then + return + end + if not creative.is_enabled_for(digger:get_player_name()) then + return old_handle_node_drops(pos, drops, digger) + end + local inv = digger:get_inventory() + if inv then + for _, item in ipairs(drops) do + if not inv:contains_item("main", item, true) then + inv:add_item("main", item) end end end diff --git a/mods/creative/inventory.lua b/mods/creative/inventory.lua index be24b3a2..0e1d813e 100644 --- a/mods/creative/inventory.lua +++ b/mods/creative/inventory.lua @@ -1,4 +1,3 @@ -creative = {} local player_inventory = {} function creative.init_creative_inventory(player) @@ -34,16 +33,14 @@ function creative.init_creative_inventory(player) end, }, player_name) - creative.update_creative_inventory(player_name, minetest.registered_items) + return player_inventory[player_name] end function creative.update_creative_inventory(player_name, tab_content) local creative_list = {} + local inv = player_inventory[player_name] or + creative.init_creative_inventory(minetest.get_player_by_name(player_name)) local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name}) - local inv = player_inventory[player_name] - if not inv then - creative.init_creative_inventory(minetest.get_player_by_name(player_name)) - end for name, def in pairs(tab_content) do if not (def.groups.not_in_creative_inventory == 1) and @@ -79,7 +76,7 @@ function creative.register_tab(name, title, items) sfinv.register_page("creative:" .. name, { title = title, is_in_nav = function(self, player, context) - return minetest.setting_getbool("creative_mode") + return creative.is_enabled_for(player:get_player_name()) end, get = function(self, player, context) local player_name = player:get_player_name() @@ -162,7 +159,7 @@ function creative.register_tab(name, title, items) end minetest.register_on_joinplayer(function(player) - creative.init_creative_inventory(player) + creative.update_creative_inventory(player:get_player_name(), minetest.registered_items) end) creative.register_tab("all", "All", minetest.registered_items) @@ -172,7 +169,7 @@ creative.register_tab("craftitems", "Items", minetest.registered_craftitems) local old_homepage_name = sfinv.get_homepage_name function sfinv.get_homepage_name(player) - if minetest.setting_getbool("creative_mode") then + if creative.is_enabled_for(player:get_player_name()) then return "creative:all" else return old_homepage_name(player) diff --git a/mods/default/README.txt b/mods/default/README.txt index d261b6b5..8af65a9c 100644 --- a/mods/default/README.txt +++ b/mods/default/README.txt @@ -17,6 +17,7 @@ Cisoun's texture pack (CC BY-SA 3.0): default_lava.png default_leaves.png default_sapling.png + default_bush_sapling.png default_stone.png default_tree.png default_tree_top.png @@ -77,10 +78,6 @@ Splizard (CC BY-SA 3.0): Zeg9 (CC BY-SA 3.0): default_coal_block.png - default_steel_block.png - default_copper_block.png - default_bronze_block.png - default_gold_block.png paramat (CC BY-SA 3.0): wieldhand.png -- Copied from character.png by Jordach (CC BY-SA 3.0) @@ -90,6 +87,7 @@ paramat (CC BY-SA 3.0): default_acacia_leaves.png default_acacia_leaves_simple.png default_acacia_sapling.png + default_acacia_bush_sapling.png default_acacia_tree.png default_acacia_tree_top.png default_acacia_wood.png @@ -115,11 +113,18 @@ paramat (CC BY-SA 3.0): default_grass_side.png default_mese_block.png default_silver_sand.png + default_mese_post_light_side.png + default_mese_post_light_side_dark.png + default_mese_post_light_top.png + default_silver_sandstone.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) + default_silver_sandstone_brick.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) + default_silver_sandstone_block.png -- Derived from a texture by GreenXenith (CC-BY-SA 3.0) brunob.santos (CC BY-SA 4.0): default_desert_cobble.png BlockMen (CC BY-SA 3.0): + default_aspen_leaves.png -- Derived from Sofar's texture default_wood.png default_clay_brick.png default_iron_ingot.png @@ -146,10 +151,12 @@ Wuzzy (CC BY-SA 3.0): sofar (CC BY-SA 3.0): default_book_written.png, based on default_book.png default_aspen_sapling - default_aspen_leaves default_aspen_tree default_aspen_tree_top, derived from default_pine_tree_top (by paramat) default_aspen_wood, derived from default_pine_wood (by paramat) + default_chest_inside + +sofar (WTFPL): default_gravel.png -- Derived from Gambit's PixelBOX texture pack light gravel Neuromancer (CC BY-SA 2.0): @@ -195,6 +202,25 @@ Ferk (CC0 1.0) default_item_smoke.png default_item_smoke.ogg, based on sound by http://opengameart.org/users/bart +npx (CC BY-SA 3.0) + default_rainforest_litter.png + default_rainforest_litter_side.png + +kaeza (CC-BY-SA 3.0): + default_desert_sandstone.png + default_desert_sandstone_brick.png + default_desert_sandstone_block.png + +kilbith (CC BY-SA 3.0): + default_steel_block.png + default_copper_block.png + default_bronze_block.png + default_gold_block.png + default_tin_block.png + default_mineral_tin.png + default_tin_ingot.png + default_tin_lump.png + Glass breaking sounds (CC BY 3.0): 1: http://www.freesound.org/people/cmusounddesign/sounds/71947/ 2: http://www.freesound.org/people/Tomlija/sounds/97669/ @@ -262,3 +288,13 @@ https://www.freesound.org/people/AGFX/packs/1253/ blukotek (CC0 1.0) https://www.freesound.org/people/blukotek/sounds/251660/ default_dig_snappy.ogg + +Chests sounds added by sofar, derived of several files mixed together: + default_chest_open.ogg + default_chest_close.ogg + - http://www.freesound.org/people/Sevin7/sounds/269722/ CC0 + - http://www.freesound.org/people/Percy%20Duke/sounds/23448/ CC-BY-3.0 + - http://www.freesound.org/people/kingsamas/sounds/135576/ CC-BY-3.0 + - http://www.freesound.org/people/bulbastre/sounds/126887/ CC-BY-3.0 + - http://www.freesound.org/people/Yoyodaman234/sounds/183541/ CC0 + diff --git a/mods/default/crafting.lua b/mods/default/crafting.lua index 483245c2..50ffb1ae 100644 --- a/mods/default/crafting.lua +++ b/mods/default/crafting.lua @@ -392,12 +392,6 @@ minetest.register_craft({ } }) -minetest.register_craft({ - type = "shapeless", - output = "default:bronze_ingot", - recipe = {"default:steel_ingot", "default:copper_ingot"}, -}) - minetest.register_craft({ output = 'default:coalblock', recipe = { @@ -446,6 +440,31 @@ minetest.register_craft({ } }) +minetest.register_craft({ + output = "default:tinblock", + recipe = { + {"default:tin_ingot", "default:tin_ingot", "default:tin_ingot"}, + {"default:tin_ingot", "default:tin_ingot", "default:tin_ingot"}, + {"default:tin_ingot", "default:tin_ingot", "default:tin_ingot"}, + } +}) + +minetest.register_craft({ + output = "default:tin_ingot 9", + recipe = { + {"default:tinblock"}, + } +}) + +minetest.register_craft({ + output = "default:bronze_ingot 9", + recipe = { + {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"}, + {"default:copper_ingot", "default:tin_ingot", "default:copper_ingot"}, + {"default:copper_ingot", "default:copper_ingot", "default:copper_ingot"}, + } +}) + minetest.register_craft({ output = 'default:bronzeblock', recipe = { @@ -495,34 +514,98 @@ minetest.register_craft({ }) minetest.register_craft({ - output = 'default:sandstone', + output = "default:sandstone", recipe = { - {'group:sand', 'group:sand'}, - {'group:sand', 'group:sand'}, + {"default:sand", "default:sand"}, + {"default:sand", "default:sand"}, } }) minetest.register_craft({ - output = 'default:sand 4', + output = "default:sand 4", recipe = { - {'default:sandstone'}, + {"default:sandstone"}, } }) minetest.register_craft({ - output = 'default:sandstonebrick 4', + output = "default:sandstonebrick 4", recipe = { - {'default:sandstone', 'default:sandstone'}, - {'default:sandstone', 'default:sandstone'}, + {"default:sandstone", "default:sandstone"}, + {"default:sandstone", "default:sandstone"}, } }) minetest.register_craft({ - output = 'default:sandstone_block 9', + output = "default:sandstone_block 9", recipe = { - {'default:sandstone', 'default:sandstone', 'default:sandstone'}, - {'default:sandstone', 'default:sandstone', 'default:sandstone'}, - {'default:sandstone', 'default:sandstone', 'default:sandstone'}, + {"default:sandstone", "default:sandstone", "default:sandstone"}, + {"default:sandstone", "default:sandstone", "default:sandstone"}, + {"default:sandstone", "default:sandstone", "default:sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:desert_sandstone", + recipe = { + {"default:desert_sand", "default:desert_sand"}, + {"default:desert_sand", "default:desert_sand"}, + } +}) + +minetest.register_craft({ + output = "default:desert_sand 4", + recipe = { + {"default:desert_sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:desert_sandstone_brick 4", + recipe = { + {"default:desert_sandstone", "default:desert_sandstone"}, + {"default:desert_sandstone", "default:desert_sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:desert_sandstone_block 9", + recipe = { + {"default:desert_sandstone", "default:desert_sandstone", "default:desert_sandstone"}, + {"default:desert_sandstone", "default:desert_sandstone", "default:desert_sandstone"}, + {"default:desert_sandstone", "default:desert_sandstone", "default:desert_sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:silver_sandstone", + recipe = { + {"default:silver_sand", "default:silver_sand"}, + {"default:silver_sand", "default:silver_sand"}, + } +}) + +minetest.register_craft({ + output = "default:silver_sand 4", + recipe = { + {"default:silver_sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:silver_sandstone_brick 4", + recipe = { + {"default:silver_sandstone", "default:silver_sandstone"}, + {"default:silver_sandstone", "default:silver_sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:silver_sandstone_block 9", + recipe = { + {"default:silver_sandstone", "default:silver_sandstone", "default:silver_sandstone"}, + {"default:silver_sandstone", "default:silver_sandstone", "default:silver_sandstone"}, + {"default:silver_sandstone", "default:silver_sandstone", "default:silver_sandstone"}, } }) @@ -582,11 +665,11 @@ minetest.register_craft({ }) minetest.register_craft({ - output = 'default:ladder_wood 3', + output = "default:ladder_wood 5", recipe = { - {'group:stick', '', 'group:stick'}, - {'group:stick', 'group:stick', 'group:stick'}, - {'group:stick', '', 'group:stick'}, + {"group:stick", "", "group:stick"}, + {"group:stick", "group:stick", "group:stick"}, + {"group:stick", "", "group:stick"}, } }) @@ -632,10 +715,19 @@ minetest.register_craft({ }) minetest.register_craft({ - output = 'default:meselamp 1', + output = 'default:meselamp', recipe = { - {'', 'default:mese_crystal',''}, - {'default:mese_crystal', 'default:glass', 'default:mese_crystal'}, + {'default:glass'}, + {'default:mese_crystal'}, + } +}) + +minetest.register_craft({ + output = "default:mese_post_light 3", + recipe = { + {"", "default:glass", ""}, + {"default:mese_crystal", "default:mese_crystal", "default:mese_crystal"}, + {"", "group:wood", ""}, } }) @@ -776,6 +868,12 @@ minetest.register_craft({ recipe = "default:copper_lump", }) +minetest.register_craft({ + type = "cooking", + output = "default:tin_ingot", + recipe = "default:tin_lump", +}) + minetest.register_craft({ type = "cooking", output = "default:gold_ingot", @@ -893,6 +991,18 @@ minetest.register_craft({ burntime = 10, }) +minetest.register_craft({ + type = "fuel", + recipe = "default:bush_sapling", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_bush_sapling", + burntime = 7, +}) + minetest.register_craft({ type = "fuel", recipe = "default:aspen_sapling", diff --git a/mods/default/craftitems.lua b/mods/default/craftitems.lua index 0c51c713..33cdd5f6 100644 --- a/mods/default/craftitems.lua +++ b/mods/default/craftitems.lua @@ -12,14 +12,23 @@ minetest.register_craftitem("default:paper", { groups = {flammable = 3}, }) + local lpp = 14 -- Lines per book's page local function book_on_use(itemstack, user) local player_name = user:get_player_name() - local data = minetest.deserialize(itemstack:get_metadata()) + local meta = itemstack:get_meta() local title, text, owner = "", "", player_name local page, page_max, lines, string = 1, 1, {}, "" - if data then + -- Backwards compatibility + local old_data = minetest.deserialize(itemstack:get_metadata()) + if old_data then + meta:from_table({ fields = old_data }) + end + + local data = meta:to_table().fields + + if data.owner then title = data.title text = data.text owner = data.owner @@ -63,6 +72,7 @@ local function book_on_use(itemstack, user) end minetest.show_formspec(player_name, "default:book", formspec) + return itemstack end minetest.register_on_player_receive_fields(function(player, formname, fields) @@ -81,35 +91,42 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) new_stack = ItemStack("default:book_written") end else - data = minetest.deserialize(stack:get_metadata()) + data = stack:get_meta():to_table().fields + end + + if data and data.owner and data.owner ~= player:get_player_name() then + return end if not data then data = {} end data.title = fields.title + data.owner = player:get_player_name() + data.description = "\""..fields.title.."\" by "..data.owner data.text = fields.text data.text_len = #data.text data.page = 1 data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) - data.owner = player:get_player_name() - local data_str = minetest.serialize(data) if new_stack then - new_stack:set_metadata(data_str) + new_stack:get_meta():from_table({ fields = data }) if inv:room_for_item("main", new_stack) then inv:add_item("main", new_stack) else minetest.add_item(player:getpos(), new_stack) end else - stack:set_metadata(data_str) + stack:get_meta():from_table({ fields = data }) end elseif fields.book_next or fields.book_prev then - local data = minetest.deserialize(stack:get_metadata()) + local data = stack:get_meta():to_table().fields if not data or not data.page then return end + data.page = tonumber(data.page) + data.page_max = tonumber(data.page_max) + if fields.book_next then data.page = data.page + 1 if data.page > data.page_max then @@ -122,11 +139,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) end end - local data_str = minetest.serialize(data) - stack:set_metadata(data_str) - book_on_use(stack, player) + stack:get_meta():from_table({fields = data}) + stack = book_on_use(stack, player) end + -- Update stack player:set_wielded_item(stack) end) @@ -167,13 +184,69 @@ minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv if not original then return end - local copymeta = original:get_metadata() + local copymeta = original:get_meta():to_table() -- copy of the book held by player's mouse cursor - itemstack:set_metadata(copymeta) + itemstack:get_meta():from_table(copymeta) -- put the book with metadata back in the craft grid craft_inv:set_stack("craft", index, original) end) +minetest.register_craftitem("default:skeleton_key", { + description = "Skeleton Key", + inventory_image = "default_key_skeleton.png", + groups = {key = 1}, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + local pos = pointed_thing.under + local node = minetest.get_node(pos) + + if not node then + return itemstack + end + + local on_skeleton_key_use = minetest.registered_nodes[node.name].on_skeleton_key_use + if not on_skeleton_key_use then + return itemstack + end + + -- make a new key secret in case the node callback needs it + local random = math.random + local newsecret = string.format( + "%04x%04x%04x%04x", + random(2^16) - 1, random(2^16) - 1, + random(2^16) - 1, random(2^16) - 1) + + local secret, _, _ = on_skeleton_key_use(pos, user, newsecret) + + if secret then + local inv = minetest.get_inventory({type="player", name=user:get_player_name()}) + + -- update original itemstack + itemstack:take_item() + + -- finish and return the new key + local new_stack = ItemStack("default:key") + local meta = new_stack:get_meta() + meta:set_string("secret", secret) + meta:set_string("description", "Key to "..user:get_player_name().."'s " + ..minetest.registered_nodes[node.name].description) + + if itemstack:get_count() == 0 then + itemstack = new_stack + else + if inv:add_item("main", new_stack):get_count() > 0 then + minetest.add_item(user:getpos(), new_stack) + end -- else: added to inventory successfully + end + + return itemstack + end + end +}) + minetest.register_craftitem("default:coal_lump", { description = "Coal Lump", inventory_image = "default_coal_lump.png", @@ -190,6 +263,11 @@ minetest.register_craftitem("default:copper_lump", { inventory_image = "default_copper_lump.png", }) +minetest.register_craftitem("default:tin_lump", { + description = "Tin Lump", + inventory_image = "default_tin_lump.png", +}) + minetest.register_craftitem("default:mese_crystal", { description = "Mese Crystal", inventory_image = "default_mese_crystal.png", @@ -220,6 +298,11 @@ minetest.register_craftitem("default:copper_ingot", { inventory_image = "default_copper_ingot.png", }) +minetest.register_craftitem("default:tin_ingot", { + description = "Tin Ingot", + inventory_image = "default_tin_ingot.png", +}) + minetest.register_craftitem("default:bronze_ingot", { description = "Bronze Ingot", inventory_image = "default_bronze_ingot.png", @@ -249,4 +332,3 @@ minetest.register_craftitem("default:flint", { description = "Flint", inventory_image = "default_flint.png" }) - diff --git a/mods/default/functions.lua b/mods/default/functions.lua index 3bda4bf0..5dc22cab 100644 --- a/mods/default/functions.lua +++ b/mods/default/functions.lua @@ -77,8 +77,6 @@ function default.node_sound_leaves_defaults(table) {name = "default_grass_footstep", gain = 0.45} table.dug = table.dug or {name = "default_grass_footstep", gain = 0.7} - table.dig = table.dig or - {name = "default_dig_crumbly", gain = 0.4} table.place = table.place or {name = "default_place_node", gain = 1.0} default.node_sound_defaults(table) @@ -133,18 +131,17 @@ default.cool_lava = function(pos, node) {pos = pos, max_hear_distance = 16, gain = 0.25}) end -minetest.register_abm({ - label = "Lava cooling", - nodenames = {"default:lava_source", "default:lava_flowing"}, - neighbors = {"group:cools_lava", "group:water"}, - interval = 1, - chance = 1, - catch_up = false, - action = function(...) - default.cool_lava(...) - end, -}) - +if minetest.settings:get_bool("enable_lavacooling") ~= false then + minetest.register_abm({ + label = "Lava cooling", + nodenames = {"default:lava_source", "default:lava_flowing"}, + neighbors = {"group:cools_lava", "group:water"}, + interval = 1, + chance = 2, + catch_up = false, + action = default.cool_lava, + }) +end -- -- optimized helper to put all items in an inventory into a drops list @@ -186,6 +183,9 @@ function default.grow_cactus(pos, node) if height == 4 or node.name ~= "air" then return end + if minetest.get_node_light(pos) < 13 then + return + end minetest.set_node(pos, {name = "default:cactus"}) return true end @@ -209,6 +209,9 @@ function default.grow_papyrus(pos, node) if height == 4 or node.name ~= "air" then return end + if minetest.get_node_light(pos) < 13 then + return + end minetest.set_node(pos, {name = "default:papyrus"}) return true end @@ -219,9 +222,7 @@ minetest.register_abm({ neighbors = {"group:sand"}, interval = 12, chance = 83, - action = function(...) - default.grow_cactus(...) - end + action = default.grow_cactus }) minetest.register_abm({ @@ -230,9 +231,7 @@ minetest.register_abm({ neighbors = {"default:dirt", "default:dirt_with_grass"}, interval = 14, chance = 71, - action = function(...) - default.grow_papyrus(...) - end + action = default.grow_papyrus }) @@ -321,47 +320,65 @@ default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) end end --- Leafdecay ABM - -minetest.register_abm({ - label = "Leaf decay", - nodenames = {"group:leafdecay"}, - neighbors = {"air"}, - interval = 2, - chance = 10, - catch_up = false, - - action = function(pos, node, _, _) - -- Check if leaf is placed - if node.param2 ~= 0 then - return +-- Leafdecay +local function leafdecay_after_destruct(pos, oldnode, def) + for _, v in pairs(minetest.find_nodes_in_area(vector.subtract(pos, def.radius), + vector.add(pos, def.radius), def.leaves)) do + local node = minetest.get_node(v) + local timer = minetest.get_node_timer(v) + if node.param2 == 0 and not timer:is_started() then + timer:start(math.random(20, 120) / 10) end + end +end - local rad = minetest.registered_nodes[node.name].groups.leafdecay - -- Assume ignore is a trunk, to make this - -- work at the border of a loaded area - if minetest.find_node_near(pos, rad, {"ignore", "group:tree"}) then - return - end - -- Drop stuff - local itemstacks = minetest.get_node_drops(node.name) - for _, itemname in ipairs(itemstacks) do - if itemname ~= node.name or - minetest.get_item_group(node.name, "leafdecay_drop") ~= 0 then - local p_drop = { - x = pos.x - 0.5 + math.random(), - y = pos.y - 0.5 + math.random(), - z = pos.z - 0.5 + math.random(), - } - minetest.add_item(p_drop, itemname) +local function leafdecay_on_timer(pos, def) + if minetest.find_node_near(pos, def.radius, def.trunks) then + return false + end + + local node = minetest.get_node(pos) + local drops = minetest.get_node_drops(node.name) + for _, item in ipairs(drops) do + local is_leaf + for _, v in pairs(def.leaves) do + if v == item then + is_leaf = true end end - -- Remove node - minetest.remove_node(pos) - minetest.check_for_falling(pos) + if minetest.get_item_group(item, "leafdecay_drop") ~= 0 or + not is_leaf then + minetest.add_item({ + x = pos.x - 0.5 + math.random(), + y = pos.y - 0.5 + math.random(), + z = pos.z - 0.5 + math.random(), + }, item) + end end -}) + minetest.remove_node(pos) + minetest.check_for_falling(pos) +end + +function default.register_leafdecay(def) + assert(def.leaves) + assert(def.trunks) + assert(def.radius) + for _, v in pairs(def.trunks) do + minetest.override_item(v, { + after_destruct = function(pos, oldnode) + leafdecay_after_destruct(pos, oldnode, def) + end, + }) + end + for _, v in pairs(def.leaves) do + minetest.override_item(v, { + on_timer = function(pos) + leafdecay_on_timer(pos, def) + end, + }) + end +end -- -- Convert dirt to something that fits the environment @@ -512,3 +529,46 @@ minetest.register_abm({ minetest.set_node(pos, {name = "default:coral_skeleton"}) end, }) + + +-- +-- NOTICE: This method is not an official part of the API yet! +-- This method may change in future. +-- + +function default.can_interact_with_node(player, pos) + if player then + if minetest.check_player_privs(player, "protection_bypass") then + return true + end + else + return false + end + + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + + if not owner or owner == "" or owner == player:get_player_name() then + return true + end + + -- is player wielding the right key? + local item = player:get_wielded_item() + if item:get_name() == "default:key" then + local key_meta = item:get_meta() + + if key_meta:get_string("secret") == "" then + local key_oldmeta = item:get_metadata() + if key_oldmeta == "" or not minetest.parse_json(key_oldmeta) then + return false + end + + key_meta:set_string("secret", minetest.parse_json(key_oldmeta).secret) + item:set_metadata("") + end + + return meta:get_string("key_lock_secret") == key_meta:get_string("secret") + end + + return false +end diff --git a/mods/default/license.txt b/mods/default/license.txt index e9267366..72af7284 100644 --- a/mods/default/license.txt +++ b/mods/default/license.txt @@ -41,6 +41,9 @@ Copyright (C) 2010-2016: asl97 KevDoy Mito551 + GreenXenith + kaeza + kilbith You are free to: Share — copy and redistribute the material in any medium or format. diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua index d786a841..1305226a 100644 --- a/mods/default/mapgen.lua +++ b/mods/default/mapgen.lua @@ -1,5 +1,5 @@ -- --- Aliases for map generator outputs +-- Aliases for map generators -- minetest.register_alias("mapgen_stone", "default:stone") @@ -34,18 +34,21 @@ minetest.register_alias("mapgen_pine_needles", "default:pine_needles") minetest.register_alias("mapgen_cobble", "default:cobble") minetest.register_alias("mapgen_stair_cobble", "stairs:stair_cobble") minetest.register_alias("mapgen_mossycobble", "default:mossycobble") +minetest.register_alias("mapgen_stair_desert_stone", "stairs:stair_desert_stone") minetest.register_alias("mapgen_sandstonebrick", "default:sandstonebrick") -minetest.register_alias("mapgen_stair_sandstonebrick", "stairs:stair_sandstonebrick") +minetest.register_alias("mapgen_stair_sandstone_block", "stairs:stair_sandstone_block") -- -- Register ores -- -function default.register_ores() - minetest.clear_registered_ores() - -- Blob ores - -- These first to avoid other ores in blobs +-- Blob ores +-- These first to avoid other ores in blobs + +-- Mgv6 + +function default.register_mgv6_blob_ores() -- Clay -- This first to avoid clay in sand blobs @@ -74,8 +77,7 @@ function default.register_ores() minetest.register_ore({ ore_type = "blob", ore = "default:sand", - wherein = {"default:stone", "default:sandstone", - "default:desert_stone"}, + wherein = {"default:stone", "default:desert_stone"}, clust_scarcity = 16 * 16 * 16, clust_size = 5, y_min = -31, @@ -110,8 +112,6 @@ function default.register_ores() octaves = 1, persist = 0.0 }, - biomes = {"taiga", "snowy_grassland", "grassland", "coniferous_forest", - "deciduous_forest", "savanna", "rainforest"} }) -- Gravel @@ -134,8 +134,123 @@ function default.register_ores() persist = 0.0 }, }) +end - -- Scatter ores + +-- All mapgens except mgv6 + +function default.register_blob_ores() + + -- Clay + + minetest.register_ore({ + ore_type = "blob", + ore = "default:clay", + wherein = {"default:sand"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_min = -15, + y_max = 0, + noise_threshold = 0.0, + noise_params = { + offset = 0.5, + scale = 0.2, + spread = {x = 5, y = 5, z = 5}, + seed = -316, + octaves = 1, + persist = 0.0 + }, + }) + + -- Silver sand + + minetest.register_ore({ + ore_type = "blob", + ore = "default:silver_sand", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_min = -31000, + y_max = 31000, + noise_threshold = 0.0, + noise_params = { + offset = 0.5, + scale = 0.2, + spread = {x = 5, y = 5, z = 5}, + seed = 2316, + octaves = 1, + persist = 0.0 + }, + biomes = {"icesheet_ocean", "tundra", "tundra_beach", "tundra_ocean", + "taiga", "taiga_ocean", "snowy_grassland", "snowy_grassland_ocean", + "grassland", "grassland_dunes", "grassland_ocean", "coniferous_forest", + "coniferous_forest_dunes", "coniferous_forest_ocean", "deciduous_forest", + "deciduous_forest_shore", "deciduous_forest_ocean", "cold_desert", + "cold_desert_ocean", "savanna", "savanna_shore", "savanna_ocean", + "rainforest", "rainforest_swamp", "rainforest_ocean", "underground", + "floatland_ocean", "floatland_grassland", "floatland_coniferous_forest"} + }) + + -- Dirt + + minetest.register_ore({ + ore_type = "blob", + ore = "default:dirt", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_min = -31, + y_max = 31000, + noise_threshold = 0.0, + noise_params = { + offset = 0.5, + scale = 0.2, + spread = {x = 5, y = 5, z = 5}, + seed = 17676, + octaves = 1, + persist = 0.0 + }, + biomes = {"taiga", "snowy_grassland", "grassland", "coniferous_forest", + "deciduous_forest", "deciduous_forest_shore", "savanna", "savanna_shore", + "rainforest", "rainforest_swamp", "floatland_grassland", + "floatland_coniferous_forest"} + }) + + -- Gravel + + minetest.register_ore({ + ore_type = "blob", + ore = "default:gravel", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_min = -31000, + y_max = 31000, + noise_threshold = 0.0, + noise_params = { + offset = 0.5, + scale = 0.2, + spread = {x = 5, y = 5, z = 5}, + seed = 766, + octaves = 1, + persist = 0.0 + }, + biomes = {"icesheet_ocean", "tundra", "tundra_beach", "tundra_ocean", + "taiga", "taiga_ocean", "snowy_grassland", "snowy_grassland_ocean", + "grassland", "grassland_dunes", "grassland_ocean", "coniferous_forest", + "coniferous_forest_dunes", "coniferous_forest_ocean", "deciduous_forest", + "deciduous_forest_shore", "deciduous_forest_ocean", "cold_desert", + "cold_desert_ocean", "savanna", "savanna_shore", "savanna_ocean", + "rainforest", "rainforest_swamp", "rainforest_ocean", "underground", + "floatland_ocean", "floatland_grassland", "floatland_coniferous_forest"} + }) +end + + +-- Scatter ores +-- All mapgens + +function default.register_ores() -- Coal @@ -242,6 +357,41 @@ function default.register_ores() y_max = -64, }) + -- Tin + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_tin", + wherein = "default:stone", + clust_scarcity = 10 * 10 * 10, + clust_num_ores = 5, + clust_size = 3, + y_min = 1025, + y_max = 31000, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_tin", + wherein = "default:stone", + clust_scarcity = 13 * 13 * 13, + clust_num_ores = 4, + clust_size = 3, + y_min = -127, + y_max = -32, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_tin", + wherein = "default:stone", + clust_scarcity = 10 * 10 * 10, + clust_num_ores = 5, + clust_size = 3, + y_min = -31000, + y_max = -128, + }) + -- Gold minetest.register_ore({ @@ -377,10 +527,9 @@ end -- Register biomes -- --- All mapgens except mgv6 and singlenode +-- All mapgens except mgv6 -function default.register_biomes() - minetest.clear_registered_biomes() +function default.register_biomes(upper_limit) -- Icesheet @@ -399,7 +548,7 @@ function default.register_biomes() node_riverbed = "default:gravel", depth_riverbed = 2, y_min = -8, - y_max = 31000, + y_max = upper_limit, heat_point = 0, humidity_point = 73, }) @@ -439,7 +588,7 @@ function default.register_biomes() node_riverbed = "default:gravel", depth_riverbed = 2, y_min = 2, - y_max = 31000, + y_max = upper_limit, heat_point = 0, humidity_point = 40, }) @@ -501,7 +650,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 2, - y_max = 31000, + y_max = upper_limit, heat_point = 25, humidity_point = 70, }) @@ -543,7 +692,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 5, - y_max = 31000, + y_max = upper_limit, heat_point = 20, humidity_point = 35, }) @@ -585,7 +734,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 6, - y_max = 31000, + y_max = upper_limit, heat_point = 50, humidity_point = 35, }) @@ -647,7 +796,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 6, - y_max = 31000, + y_max = upper_limit, heat_point = 45, humidity_point = 70, }) @@ -709,7 +858,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 1, - y_max = 31000, + y_max = upper_limit, heat_point = 60, humidity_point = 68, }) @@ -771,7 +920,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 5, - y_max = 31000, + y_max = upper_limit, heat_point = 92, humidity_point = 16, }) @@ -804,7 +953,7 @@ function default.register_biomes() node_top = "default:sand", depth_top = 1, node_filler = "default:sand", - depth_filler = 0, + depth_filler = 1, node_stone = "default:sandstone", --node_water_top = "", --depth_water_top = , @@ -813,7 +962,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 5, - y_max = 31000, + y_max = upper_limit, heat_point = 60, humidity_point = 0, }) @@ -855,7 +1004,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 5, - y_max = 31000, + y_max = upper_limit, heat_point = 40, humidity_point = 0, }) @@ -897,7 +1046,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 1, - y_max = 31000, + y_max = upper_limit, heat_point = 89, humidity_point = 42, }) @@ -947,7 +1096,7 @@ function default.register_biomes() minetest.register_biome({ name = "rainforest", --node_dust = "", - node_top = "default:dirt_with_grass", + node_top = "default:dirt_with_rainforest_litter", depth_top = 1, node_filler = "default:dirt", depth_filler = 3, @@ -959,7 +1108,7 @@ function default.register_biomes() node_riverbed = "default:sand", depth_riverbed = 2, y_min = 1, - y_max = 31000, + y_max = upper_limit, heat_point = 86, humidity_point = 65, }) @@ -1026,6 +1175,100 @@ function default.register_biomes() end +-- Biomes for floatlands + +function default.register_floatland_biomes(floatland_level, shadow_limit) + + -- Coniferous forest + + minetest.register_biome({ + name = "floatland_coniferous_forest", + --node_dust = "", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + --node_stone = "", + --node_water_top = "", + --depth_water_top = , + --node_water = "", + --node_river_water = "", + --node_riverbed = "", + --depth_riverbed = , + y_min = floatland_level + 2, + y_max = 31000, + heat_point = 50, + humidity_point = 70, + }) + + -- Grassland + + minetest.register_biome({ + name = "floatland_grassland", + --node_dust = "", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + --node_stone = "", + --node_water_top = "", + --depth_water_top = , + --node_water = "", + --node_river_water = "", + --node_riverbed = "", + --depth_riverbed = , + y_min = floatland_level + 2, + y_max = 31000, + heat_point = 50, + humidity_point = 35, + }) + + -- Sandstone desert + + minetest.register_biome({ + name = "floatland_sandstone_desert", + --node_dust = "", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 1, + node_stone = "default:sandstone", + --node_water_top = "", + --depth_water_top = , + --node_water = "", + --node_river_water = "", + --node_riverbed = "", + --depth_riverbed = , + y_min = floatland_level + 2, + y_max = 31000, + heat_point = 50, + humidity_point = 0, + }) + + -- Floatland ocean / underground + + minetest.register_biome({ + name = "floatland_ocean", + --node_dust = "", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + --node_stone = "", + --node_water_top = "", + --depth_water_top = , + --node_water = "", + --node_river_water = "", + --node_riverbed = "", + --depth_riverbed = , + y_min = shadow_limit, + y_max = floatland_level + 1, + heat_point = 50, + humidity_point = 50, + }) +end + + -- -- Register decorations -- @@ -1033,7 +1276,6 @@ end -- Mgv6 function default.register_mgv6_decorations() - minetest.clear_registered_decorations() -- Papyrus @@ -1137,7 +1379,8 @@ local function register_grass_decoration(offset, scale, length) persist = 0.6 }, biomes = {"grassland", "grassland_dunes", "deciduous_forest", - "coniferous_forest", "coniferous_forest_dunes"}, + "coniferous_forest", "coniferous_forest_dunes", + "floatland_grassland", "floatland_coniferous_forest"}, y_min = 1, y_max = 31000, decoration = "default:grass_" .. length, @@ -1166,7 +1409,6 @@ end function default.register_decorations() - minetest.clear_registered_decorations() -- Apple tree and log @@ -1187,6 +1429,7 @@ function default.register_decorations() y_max = 31000, schematic = minetest.get_modpath("default") .. "/schematics/apple_tree.mts", flags = "place_center_x, place_center_z", + rotation = "random", }) minetest.register_decoration({ @@ -1204,20 +1447,7 @@ function default.register_decorations() biomes = {"deciduous_forest"}, y_min = 1, y_max = 31000, - schematic = { - size = {x = 3, y = 3, z = 1}, - data = { - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "default:tree", param2 = 12, prob = 191}, - {name = "default:tree", param2 = 12}, - {name = "default:tree", param2 = 12, prob = 127}, - {name = "air", prob = 0}, - {name = "flowers:mushroom_brown", prob = 63}, - {name = "air", prob = 0}, - }, - }, + schematic = minetest.get_modpath("default") .. "/schematics/apple_log.mts", flags = "place_center_x", rotation = "random", }) @@ -1226,8 +1456,8 @@ function default.register_decorations() minetest.register_decoration({ deco_type = "schematic", - place_on = {"default:dirt_with_grass", "default:dirt"}, - sidelen = 80, + place_on = {"default:dirt_with_rainforest_litter", "default:dirt"}, + sidelen = 16, fill_ratio = 0.1, biomes = {"rainforest", "rainforest_swamp"}, y_min = -1, @@ -1239,26 +1469,13 @@ function default.register_decorations() minetest.register_decoration({ deco_type = "schematic", - place_on = {"default:dirt_with_grass", "default:dirt"}, - sidelen = 80, + place_on = {"default:dirt_with_rainforest_litter", "default:dirt"}, + sidelen = 16, fill_ratio = 0.005, biomes = {"rainforest", "rainforest_swamp"}, y_min = 1, y_max = 31000, - schematic = { - size = {x = 3, y = 3, z = 1}, - data = { - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "default:jungletree", param2 = 12, prob = 191}, - {name = "default:jungletree", param2 = 12}, - {name = "default:jungletree", param2 = 12, prob = 127}, - {name = "air", prob = 0}, - {name = "flowers:mushroom_brown", prob = 127}, - {name = "air", prob = 0}, - }, - }, + schematic = minetest.get_modpath("default") .. "/schematics/jungle_log.mts", flags = "place_center_x", rotation = "random", }) @@ -1277,7 +1494,7 @@ function default.register_decorations() octaves = 3, persist = 0.66 }, - biomes = {"taiga", "coniferous_forest"}, + biomes = {"taiga", "coniferous_forest", "floatland_coniferous_forest"}, y_min = 2, y_max = 31000, schematic = minetest.get_modpath("default") .. "/schematics/pine_tree.mts", @@ -1299,20 +1516,7 @@ function default.register_decorations() biomes = {"taiga", "coniferous_forest"}, y_min = 1, y_max = 31000, - schematic = { - size = {x = 3, y = 3, z = 1}, - data = { - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "default:pine_tree", param2 = 12, prob = 191}, - {name = "default:pine_tree", param2 = 12}, - {name = "default:pine_tree", param2 = 12, prob = 127}, - {name = "air", prob = 0}, - {name = "flowers:mushroom_red", prob = 63}, - {name = "air", prob = 0}, - }, - }, + schematic = minetest.get_modpath("default") .. "/schematics/pine_log.mts", flags = "place_center_x", rotation = "random", }) @@ -1354,17 +1558,7 @@ function default.register_decorations() biomes = {"savanna"}, y_min = 1, y_max = 31000, - schematic = { - size = {x = 3, y = 2, z = 1}, - data = { - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "default:acacia_tree", param2 = 12, prob = 191}, - {name = "default:acacia_tree", param2 = 12}, - {name = "default:acacia_tree", param2 = 12, prob = 127}, - }, - }, + schematic = minetest.get_modpath("default") .. "/schematics/acacia_log.mts", flags = "place_center_x", rotation = "random", }) @@ -1405,20 +1599,7 @@ function default.register_decorations() biomes = {"deciduous_forest"}, y_min = 1, y_max = 31000, - schematic = { - size = {x = 3, y = 3, z = 1}, - data = { - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "air", prob = 0}, - {name = "default:aspen_tree", param2 = 12}, - {name = "default:aspen_tree", param2 = 12}, - {name = "default:aspen_tree", param2 = 12, prob = 127}, - {name = "flowers:mushroom_red", prob = 63}, - {name = "flowers:mushroom_brown", prob = 63}, - {name = "air", prob = 0}, - }, - }, + schematic = minetest.get_modpath("default") .. "/schematics/aspen_log.mts", flags = "place_center_x", rotation = "random", }) @@ -1501,7 +1682,8 @@ function default.register_decorations() octaves = 3, persist = 0.7, }, - biomes = {"snowy_grassland", "grassland", "deciduous_forest"}, + biomes = {"snowy_grassland", "grassland", "deciduous_forest", + "floatland_grassland"}, y_min = 1, y_max = 31000, schematic = minetest.get_modpath("default") .. "/schematics/bush.mts", @@ -1549,8 +1731,8 @@ function default.register_decorations() minetest.register_decoration({ deco_type = "simple", - place_on = {"default:dirt_with_grass"}, - sidelen = 80, + place_on = {"default:dirt_with_rainforest_litter"}, + sidelen = 16, fill_ratio = 0.1, biomes = {"rainforest"}, y_min = 1, @@ -1585,9 +1767,9 @@ function default.register_decorations() deco_type = "schematic", place_on = {"default:sand"}, noise_params = { - offset = -0.1, + offset = -0.15, scale = 0.1, - spread = {x = 200, y = 200, z = 200}, + spread = {x = 100, y = 100, z = 100}, seed = 7013, octaves = 3, persist = 1, @@ -1607,15 +1789,38 @@ end -- --- Detect mapgen to select functions +-- Detect mapgen, flags and parameters to select functions -- +-- Get setting or default +local mgv7_spflags = minetest.get_mapgen_setting("mgv7_spflags") or + "mountains, ridges, nofloatlands" +local captures_float = string.match(mgv7_spflags, "floatlands") +local captures_nofloat = string.match(mgv7_spflags, "nofloatlands") + +local mgv7_floatland_level = minetest.get_mapgen_setting("mgv7_floatland_level") or 1280 +local mgv7_shadow_limit = minetest.get_mapgen_setting("mgv7_shadow_limit") or 1024 + +minetest.clear_registered_biomes() +minetest.clear_registered_ores() +minetest.clear_registered_decorations() + local mg_name = minetest.get_mapgen_setting("mg_name") if mg_name == "v6" then + default.register_mgv6_blob_ores() default.register_ores() default.register_mgv6_decorations() +elseif mg_name == "v7" and captures_float == "floatlands" and + captures_nofloat ~= "nofloatlands" then + -- Mgv7 with floatlands + default.register_biomes(mgv7_shadow_limit - 1) + default.register_floatland_biomes(mgv7_floatland_level, mgv7_shadow_limit) + default.register_blob_ores() + default.register_ores() + default.register_decorations() else - default.register_biomes() + default.register_biomes(31000) + default.register_blob_ores() default.register_ores() default.register_decorations() end diff --git a/mods/default/models/chest_open.obj b/mods/default/models/chest_open.obj new file mode 100644 index 00000000..72ba175a --- /dev/null +++ b/mods/default/models/chest_open.obj @@ -0,0 +1,79 @@ +# Blender v2.78 (sub 0) OBJ File: 'chest-open.blend' +# www.blender.org +o Top_Cube.002_None_Top_Cube.002_None_bottom +v -0.500000 0.408471 0.720970 +v -0.500000 1.115578 0.013863 +v -0.500000 0.894607 -0.207108 +v -0.500000 0.187501 0.499999 +v 0.500000 1.115578 0.013863 +v 0.500000 0.408471 0.720970 +v 0.500000 0.187501 0.499999 +v 0.500000 0.894607 -0.207108 +v -0.500000 0.187500 -0.500000 +v -0.500000 -0.500000 -0.500000 +v -0.500000 -0.500000 0.500000 +v 0.500000 0.187500 -0.500000 +v 0.500000 -0.500000 0.500000 +v 0.500000 -0.500000 -0.500000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 1.0000 +vt 1.0000 0.6875 +vt 0.0000 0.6875 +vt 1.0000 1.0000 +vt 0.0000 0.6875 +vt 1.0000 0.6875 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 0.0000 0.0000 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 1.0000 0.6875 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.6875 +vt 0.0000 0.6875 +vt 0.0000 0.0000 +vt 1.0000 0.5000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vn 0.0000 0.7071 0.7071 +vn -0.0000 -1.0000 -0.0000 +vn -1.0000 0.0000 0.0000 +vn 1.0000 0.0000 -0.0000 +vn 0.0000 -0.7071 0.7071 +vn 0.0000 0.0000 1.0000 +vn -0.0000 0.7071 -0.7071 +vn -0.0000 0.0000 -1.0000 +vn -0.0000 -0.7071 -0.7071 +vn -0.0000 1.0000 -0.0000 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Top +s off +f 6/1/1 5/2/1 2/3/1 1/4/1 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Bottom +f 11/5/2 10/6/2 14/7/2 13/8/2 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Right-Left +f 1/9/3 2/10/3 3/11/3 4/12/3 +f 5/13/4 6/1/4 7/14/4 8/15/4 +f 4/12/3 9/16/3 10/17/3 11/18/3 +f 12/19/4 7/14/4 13/8/4 14/20/4 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Back +f 6/21/5 1/9/5 4/12/5 7/22/5 +f 7/22/6 4/12/6 11/18/6 13/23/6 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Front +f 2/10/7 5/24/7 8/25/7 3/11/7 +f 9/16/8 12/26/8 14/27/8 10/17/8 +g Top_Cube.002_None_Top_Cube.002_None_bottom_Top_Cube.002_None_Top_Cube.002_None_bottom_Inside +f 4/28/9 3/29/9 8/30/9 7/31/9 +f 7/31/10 12/32/10 9/33/10 4/28/10 diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua index 3e781091..f14e8b21 100644 --- a/mods/default/nodes.lua +++ b/mods/default/nodes.lua @@ -30,6 +30,12 @@ default:desert_stone_block default:sandstone default:sandstonebrick default:sandstone_block +default:desert_sandstone +default:desert_sandstone_brick +default:desert_sandstone_block +default:silver_sandstone +default:silver_sandstone_brick +default:silver_sandstone_block default:obsidian default:obsidianbrick @@ -44,6 +50,7 @@ default:dirt_with_grass default:dirt_with_grass_footsteps default:dirt_with_dry_grass default:dirt_with_snow +default:dirt_with_rainforest_litter default:sand default:desert_sand @@ -100,6 +107,10 @@ default:steelblock default:stone_with_copper default:copperblock + +default:stone_with_tin +default:tinblock + default:bronzeblock default:stone_with_gold @@ -133,8 +144,10 @@ default:dry_grass_5 default:bush_stem default:bush_leaves +default:bush_sapling default:acacia_bush_stem default:acacia_bush_leaves +default:acacia_bush_sapling Corals ------ @@ -182,6 +195,7 @@ default:obsidian_glass default:brick default:meselamp +default:mese_post_light Misc ---- @@ -273,7 +287,6 @@ minetest.register_node("default:desert_stone_block", { sounds = default.node_sound_stone_defaults(), }) - minetest.register_node("default:sandstone", { description = "Sandstone", tiles = {"default_sandstone.png"}, @@ -299,6 +312,55 @@ minetest.register_node("default:sandstone_block", { sounds = default.node_sound_stone_defaults(), }) +minetest.register_node("default:desert_sandstone", { + description = "Desert Sandstone", + tiles = {"default_desert_sandstone.png"}, + groups = {crumbly = 1, cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:desert_sandstone_brick", { + description = "Desert Sandstone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_desert_sandstone_brick.png"}, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:desert_sandstone_block", { + description = "Desert Sandstone Block", + tiles = {"default_desert_sandstone_block.png"}, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:silver_sandstone", { + description = "Silver Sandstone", + tiles = {"default_silver_sandstone.png"}, + groups = {crumbly = 1, cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:silver_sandstone_brick", { + description = "Silver Sandstone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_silver_sandstone_brick.png"}, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:silver_sandstone_block", { + description = "Silver Sandstone Block", + tiles = {"default_silver_sandstone_block.png"}, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) minetest.register_node("default:obsidian", { description = "Obsidian", @@ -378,13 +440,28 @@ minetest.register_node("default:dirt_with_snow", { tiles = {"default_snow.png", "default_dirt.png", {name = "default_dirt.png^default_snow_side.png", tileable_vertical = false}}, - groups = {crumbly = 3, soil = 1, spreading_dirt_type = 1}, + groups = {crumbly = 3, spreading_dirt_type = 1, snowy = 1}, drop = 'default:dirt', sounds = default.node_sound_dirt_defaults({ footstep = {name = "default_snow_footstep", gain = 0.15}, }), }) +minetest.register_node("default:dirt_with_rainforest_litter", { + description = "Dirt with Rainforest Litter", + tiles = { + "default_rainforest_litter.png", + "default_dirt.png", + {name = "default_dirt.png^default_rainforest_litter_side.png", + tileable_vertical = false} + }, + groups = {crumbly = 3, soil = 1, spreading_dirt_type = 1}, + drop = "default:dirt", + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_grass_footstep", gain = 0.4}, + }), +}) + minetest.register_node("default:sand", { description = "Sand", tiles = {"default_sand.png"}, @@ -445,7 +522,7 @@ minetest.register_node("default:snow", { {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, }, }, - groups = {crumbly = 3, falling_node = 1, puts_out_fire = 1}, + groups = {crumbly = 3, falling_node = 1, puts_out_fire = 1, snowy = 1}, sounds = default.node_sound_dirt_defaults({ footstep = {name = "default_snow_footstep", gain = 0.15}, dug = {name = "default_snow_footstep", gain = 0.2}, @@ -463,7 +540,7 @@ minetest.register_node("default:snow", { minetest.register_node("default:snowblock", { description = "Snow Block", tiles = {"default_snow.png"}, - groups = {crumbly = 3, puts_out_fire = 1, cools_lava = 1}, + groups = {crumbly = 3, puts_out_fire = 1, cools_lava = 1, snowy = 1}, sounds = default.node_sound_dirt_defaults({ footstep = {name = "default_snow_footstep", gain = 0.15}, dug = {name = "default_snow_footstep", gain = 0.2}, @@ -515,7 +592,6 @@ minetest.register_node("default:wood", { minetest.register_node("default:sapling", { description = "Sapling", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_sapling.png"}, inventory_image = "default_sapling.png", wield_image = "default_sapling.png", @@ -581,7 +657,6 @@ minetest.register_node("default:leaves", { minetest.register_node("default:apple", { description = "Apple", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_apple.png"}, inventory_image = "default_apple.png", paramtype = "light", @@ -618,7 +693,7 @@ minetest.register_node("default:jungletree", { }) minetest.register_node("default:junglewood", { - description = "Junglewood Planks", + description = "Jungle Wood Planks", paramtype2 = "facedir", place_param2 = 0, tiles = {"default_junglewood.png"}, @@ -651,7 +726,6 @@ minetest.register_node("default:jungleleaves", { minetest.register_node("default:junglesapling", { description = "Jungle Sapling", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_junglesapling.png"}, inventory_image = "default_junglesapling.png", wield_image = "default_junglesapling.png", @@ -731,7 +805,6 @@ minetest.register_node("default:pine_needles",{ minetest.register_node("default:pine_sapling", { description = "Pine Sapling", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_pine_sapling.png"}, inventory_image = "default_pine_sapling.png", wield_image = "default_pine_sapling.png", @@ -812,7 +885,6 @@ minetest.register_node("default:acacia_leaves", { minetest.register_node("default:acacia_sapling", { description = "Acacia Tree Sapling", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_acacia_sapling.png"}, inventory_image = "default_acacia_sapling.png", wield_image = "default_acacia_sapling.png", @@ -891,7 +963,6 @@ minetest.register_node("default:aspen_leaves", { minetest.register_node("default:aspen_sapling", { description = "Aspen Tree Sapling", drawtype = "plantlike", - visual_scale = 1.0, tiles = {"default_aspen_sapling.png"}, inventory_image = "default_aspen_sapling.png", wield_image = "default_aspen_sapling.png", @@ -979,6 +1050,24 @@ minetest.register_node("default:copperblock", { sounds = default.node_sound_metal_defaults(), }) + +minetest.register_node("default:stone_with_tin", { + description = "Tin Ore", + tiles = {"default_stone.png^default_mineral_tin.png"}, + groups = {cracky = 2}, + drop = "default:tin_lump", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:tinblock", { + description = "Tin Block", + tiles = {"default_tin_block.png"}, + is_ground_content = false, + groups = {cracky = 1, level = 2}, + sounds = default.node_sound_metal_defaults(), +}) + + minetest.register_node("default:bronzeblock", { description = "Bronze Block", tiles = {"default_bronze_block.png"}, @@ -1078,7 +1167,6 @@ minetest.register_node("default:dry_shrub", { description = "Dry Shrub", drawtype = "plantlike", waving = 1, - visual_scale = 1.0, tiles = {"default_dry_shrub.png"}, inventory_image = "default_dry_shrub.png", wield_image = "default_dry_shrub.png", @@ -1098,7 +1186,7 @@ minetest.register_node("default:junglegrass", { description = "Jungle Grass", drawtype = "plantlike", waving = 1, - visual_scale = 1.3, + visual_scale = 1.69, tiles = {"default_junglegrass.png"}, inventory_image = "default_junglegrass.png", wield_image = "default_junglegrass.png", @@ -1106,7 +1194,7 @@ minetest.register_node("default:junglegrass", { sunlight_propagates = true, walkable = false, buildable_to = true, - groups = {snappy = 3, flora = 1, attached_node = 1, grass = 1, flammable = 1}, + groups = {snappy = 3, flora = 1, attached_node = 1, flammable = 1}, sounds = default.node_sound_leaves_defaults(), selection_box = { type = "fixed", @@ -1222,7 +1310,7 @@ end minetest.register_node("default:bush_stem", { description = "Bush Stem", drawtype = "plantlike", - visual_scale = 1.18, + visual_scale = 1.41, tiles = {"default_bush_stem.png"}, inventory_image = "default_bush_stem.png", wield_image = "default_bush_stem.png", @@ -1232,7 +1320,7 @@ minetest.register_node("default:bush_stem", { sounds = default.node_sound_wood_defaults(), selection_box = { type = "fixed", - fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.54, 7 / 16}, + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.5, 7 / 16}, }, }) @@ -1243,13 +1331,57 @@ minetest.register_node("default:bush_leaves", { tiles = {"default_leaves_simple.png"}, paramtype = "light", groups = {snappy = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:bush_sapling"}, rarity = 5}, + {items = {"default:bush_leaves"}} + } + }, sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:bush_sapling", { + description = "Bush Sapling", + drawtype = "plantlike", + tiles = {"default_bush_sapling.png"}, + inventory_image = "default_bush_sapling.png", + wield_image = "default_bush_sapling.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + on_timer = default.grow_sapling, + selection_box = { + type = "fixed", + fixed = {-4 / 16, -0.5, -4 / 16, 4 / 16, 2 / 16, 4 / 16} + }, + groups = {snappy = 2, dig_immediate = 3, flammable = 2, + attached_node = 1, sapling = 1}, + sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(1200, 2400)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:bush_sapling", + -- minp, maxp to be checked, relative to sapling pos + {x = -1, y = 0, z = -1}, + {x = 1, y = 1, z = 1}, + -- maximum interval of interior volume check + 2) + + return itemstack + end, }) minetest.register_node("default:acacia_bush_stem", { description = "Acacia Bush Stem", drawtype = "plantlike", - visual_scale = 1.18, + visual_scale = 1.41, tiles = {"default_acacia_bush_stem.png"}, inventory_image = "default_acacia_bush_stem.png", wield_image = "default_acacia_bush_stem.png", @@ -1259,7 +1391,7 @@ minetest.register_node("default:acacia_bush_stem", { sounds = default.node_sound_wood_defaults(), selection_box = { type = "fixed", - fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.54, 7 / 16}, + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.5, 7 / 16}, }, }) @@ -1270,7 +1402,51 @@ minetest.register_node("default:acacia_bush_leaves", { tiles = {"default_acacia_leaves_simple.png"}, paramtype = "light", groups = {snappy = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:acacia_bush_sapling"}, rarity = 5}, + {items = {"default:acacia_bush_leaves"}} + } + }, sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:acacia_bush_sapling", { + description = "Acacia Bush Sapling", + drawtype = "plantlike", + tiles = {"default_acacia_bush_sapling.png"}, + inventory_image = "default_acacia_bush_sapling.png", + wield_image = "default_acacia_bush_sapling.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + on_timer = default.grow_sapling, + selection_box = { + type = "fixed", + fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, 2 / 16, 3 / 16} + }, + groups = {snappy = 2, dig_immediate = 3, flammable = 2, + attached_node = 1, sapling = 1}, + sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(1200, 2400)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:acacia_bush_sapling", + -- minp, maxp to be checked, relative to sapling pos + {x = -1, y = 0, z = -1}, + {x = 1, y = 1, z = 1}, + -- maximum interval of interior volume check + 2) + + return itemstack + end, }) @@ -1590,19 +1766,7 @@ minetest.register_node("default:lava_flowing", { -- Tools / "Advanced" crafting / Non-"natural" -- -local chest_formspec = - "size[8,9]" .. - default.gui_bg .. - default.gui_bg_img .. - default.gui_slots .. - "list[current_name;main;0,0.3;8,4;]" .. - "list[current_player;main;0,4.85;8,1;]" .. - "list[current_player;main;0,6.08;8,3;8]" .. - "listring[current_name;main]" .. - "listring[current_player;main]" .. - default.get_hotbar_bg(0,4.85) - -local function get_locked_chest_formspec(pos) +local function get_chest_formspec(pos) local spos = pos.x .. "," .. pos.y .. "," .. pos.z local formspec = "size[8,9]" .. @@ -1615,190 +1779,287 @@ local function get_locked_chest_formspec(pos) "listring[nodemeta:" .. spos .. ";main]" .. "listring[current_player;main]" .. default.get_hotbar_bg(0,4.85) - return formspec + return formspec end -local function has_locked_chest_privilege(meta, player) - if player then - if minetest.check_player_privs(player, "protection_bypass") then - return true - end - else +local function chest_lid_obstructed(pos) + local above = { x = pos.x, y = pos.y + 1, z = pos.z } + local def = minetest.registered_nodes[minetest.get_node(above).name] + -- allow ladders, signs, wallmounted things and torches to not obstruct + if def.drawtype == "airlike" or + def.drawtype == "signlike" or + def.drawtype == "torchlike" or + (def.drawtype == "nodebox" and def.paramtype2 == "wallmounted") then return false end - - -- is player wielding the right key? - local item = player:get_wielded_item() - if item:get_name() == "default:key" then - local key_meta = minetest.parse_json(item:get_metadata()) - local secret = meta:get_string("key_lock_secret") - if secret ~= key_meta.secret then - return false - end - - return true - end - - if player:get_player_name() ~= meta:get_string("owner") then - return false - end - return true end -minetest.register_node("default:chest", { - description = "Chest", - tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png", - "default_chest_side.png", "default_chest_side.png", "default_chest_front.png"}, - paramtype2 = "facedir", - groups = {choppy = 2, oddly_breakable_by_hand = 2}, - legacy_facedir_simple = true, - is_ground_content = false, - sounds = default.node_sound_wood_defaults(), +local open_chests = {} - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("formspec", chest_formspec) - local inv = meta:get_inventory() - inv:set_size("main", 8*4) - end, - can_dig = function(pos,player) - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - return inv:is_empty("main") - end, - on_metadata_inventory_move = function(pos, from_list, from_index, +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "default:chest" then + return + end + if not player or not fields.quit then + return + end + local pn = player:get_player_name() + + if not open_chests[pn] then + return + end + + local pos = open_chests[pn].pos + local sound = open_chests[pn].sound + local swap = open_chests[pn].swap + local node = minetest.get_node(pos) + + open_chests[pn] = nil + for k, v in pairs(open_chests) do + if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then + return true + end + end + minetest.after(0.2, minetest.swap_node, pos, { name = "default:" .. swap, + param2 = node.param2 }) + minetest.sound_play(sound, {gain = 0.3, pos = pos, max_hear_distance = 10}) + return true +end) + +function default.register_chest(name, d) + local def = table.copy(d) + def.drawtype = "mesh" + def.visual = "mesh" + def.paramtype = "light" + def.paramtype2 = "facedir" + def.legacy_facedir_simple = true + def.is_ground_content = false + + if def.protected then + def.on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Locked Chest") + meta:set_string("owner", "") + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + end + def.after_place_node = function(pos, placer) + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name() or "") + meta:set_string("infotext", "Locked Chest (owned by " .. + meta:get_string("owner") .. ")") + end + def.can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") and + default.can_interact_with_node(player, pos) + end + def.allow_metadata_inventory_move = function(pos, from_list, from_index, + to_list, to_index, count, player) + if not default.can_interact_with_node(player, pos) then + return 0 + end + return count + end + def.allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if not default.can_interact_with_node(player, pos) then + return 0 + end + return stack:get_count() + end + def.allow_metadata_inventory_take = function(pos, listname, index, stack, player) + if not default.can_interact_with_node(player, pos) then + return 0 + end + return stack:get_count() + end + def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not default.can_interact_with_node(clicker, pos) then + return itemstack + end + + minetest.sound_play(def.sound_open, {gain = 0.3, + pos = pos, max_hear_distance = 10}) + if not chest_lid_obstructed(pos) then + minetest.swap_node(pos, + { name = "default:" .. name .. "_open", + param2 = node.param2 }) + end + minetest.after(0.2, minetest.show_formspec, + clicker:get_player_name(), + "default:chest", get_chest_formspec(pos)) + open_chests[clicker:get_player_name()] = { pos = pos, + sound = def.sound_close, swap = name } + end + def.on_blast = function() end + def.on_key_use = function(pos, player) + local secret = minetest.get_meta(pos):get_string("key_lock_secret") + local itemstack = player:get_wielded_item() + local key_meta = itemstack:get_meta() + + if key_meta:get_string("secret") == "" then + key_meta:set_string("secret", minetest.parse_json(itemstack:get_metadata()).secret) + itemstack:set_metadata("") + end + + if secret ~= key_meta:get_string("secret") then + return + end + + minetest.show_formspec( + player:get_player_name(), + "default:chest_locked", + get_chest_formspec(pos) + ) + end + def.on_skeleton_key_use = function(pos, player, newsecret) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local pn = player:get_player_name() + + -- verify placer is owner of lockable chest + if owner ~= pn then + minetest.record_protection_violation(pos, pn) + minetest.chat_send_player(pn, "You do not own this chest.") + return nil + end + + local secret = meta:get_string("key_lock_secret") + if secret == "" then + secret = newsecret + meta:set_string("key_lock_secret", secret) + end + + return secret, "a locked chest", owner + end + else + def.on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Chest") + local inv = meta:get_inventory() + inv:set_size("main", 8*4) + end + def.can_dig = function(pos,player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("main") + end + def.on_rightclick = function(pos, node, clicker) + minetest.sound_play(def.sound_open, {gain = 0.3, pos = pos, + max_hear_distance = 10}) + if not chest_lid_obstructed(pos) then + minetest.swap_node(pos, { + name = "default:" .. name .. "_open", + param2 = node.param2 }) + end + minetest.after(0.2, minetest.show_formspec, + clicker:get_player_name(), + "default:chest", get_chest_formspec(pos)) + open_chests[clicker:get_player_name()] = { pos = pos, + sound = def.sound_close, swap = name } + end + end + + def.on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) minetest.log("action", player:get_player_name() .. " moves stuff in chest at " .. minetest.pos_to_string(pos)) - end, - on_metadata_inventory_put = function(pos, listname, index, stack, player) + end + def.on_metadata_inventory_put = function(pos, listname, index, stack, player) minetest.log("action", player:get_player_name() .. " moves " .. stack:get_name() .. " to chest at " .. minetest.pos_to_string(pos)) - end, - on_metadata_inventory_take = function(pos, listname, index, stack, player) + end + def.on_metadata_inventory_take = function(pos, listname, index, stack, player) minetest.log("action", player:get_player_name() .. " takes " .. stack:get_name() .. " from chest at " .. minetest.pos_to_string(pos)) - end, - on_blast = function(pos) + end + def.on_blast = function(pos) local drops = {} default.get_inventory_drops(pos, "main", drops) drops[#drops+1] = "default:chest" minetest.remove_node(pos) return drops - end, -}) + end -minetest.register_node("default:chest_locked", { - description = "Locked Chest", - tiles = {"default_chest_top.png", "default_chest_top.png", "default_chest_side.png", - "default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"}, - paramtype2 = "facedir", - groups = {choppy = 2, oddly_breakable_by_hand = 2}, - legacy_facedir_simple = true, - is_ground_content = false, + local def_opened = table.copy(def) + local def_closed = table.copy(def) + + def_opened.mesh = "chest_open.obj" + def_opened.drop = "default:" .. name + def_opened.groups.not_in_creative_inventory = 1 + def_opened.selection_box = { + type = "fixed", + fixed = { -1/2, -1/2, -1/2, 1/2, 3/16, 1/2 }, + } + def_opened.can_dig = function() + return false + end + + def_closed.mesh = nil + def_closed.drawtype = nil + def_closed.tiles[6] = def.tiles[5] -- swap textures around for "normal" + def_closed.tiles[5] = def.tiles[3] -- drawtype to make them match the mesh + def_closed.tiles[3] = def.tiles[3].."^[transformFX" + + minetest.register_node("default:" .. name, def_closed) + minetest.register_node("default:" .. name .. "_open", def_opened) + + -- convert old chests to this new variant + minetest.register_lbm({ + label = "update chests to opening chests", + name = "default:upgrade_" .. name .. "_v2", + nodenames = {"default:" .. name}, + action = function(pos, node) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", nil) + local inv = meta:get_inventory() + local list = inv:get_list("default:chest") + if list then + inv:set_size("main", 8*4) + inv:set_list("main", list) + inv:set_list("default:chest", nil) + end + end + }) +end + + +default.register_chest("chest", { + description = "Chest", + tiles = { + "default_chest_top.png", + "default_chest_top.png", + "default_chest_side.png", + "default_chest_side.png", + "default_chest_front.png", + "default_chest_inside.png" + }, sounds = default.node_sound_wood_defaults(), - - after_place_node = function(pos, placer) - local meta = minetest.get_meta(pos) - meta:set_string("owner", placer:get_player_name() or "") - meta:set_string("infotext", "Locked Chest (owned by " .. - meta:get_string("owner") .. ")") - end, - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_string("owner", "") - local inv = meta:get_inventory() - inv:set_size("main", 8 * 4) - end, - can_dig = function(pos,player) - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - return inv:is_empty("main") and has_locked_chest_privilege(meta, player) - end, - allow_metadata_inventory_move = function(pos, from_list, from_index, - to_list, to_index, count, player) - local meta = minetest.get_meta(pos) - if not has_locked_chest_privilege(meta, player) then - return 0 - end - return count - end, - allow_metadata_inventory_put = function(pos, listname, index, stack, player) - local meta = minetest.get_meta(pos) - if not has_locked_chest_privilege(meta, player) then - return 0 - end - return stack:get_count() - end, - allow_metadata_inventory_take = function(pos, listname, index, stack, player) - local meta = minetest.get_meta(pos) - if not has_locked_chest_privilege(meta, player) then - return 0 - end - return stack:get_count() - end, - on_metadata_inventory_put = function(pos, listname, index, stack, player) - minetest.log("action", player:get_player_name() .. - " moves " .. stack:get_name() .. - " to locked chest at " .. minetest.pos_to_string(pos)) - end, - on_metadata_inventory_take = function(pos, listname, index, stack, player) - minetest.log("action", player:get_player_name() .. - " takes " .. stack:get_name() .. - " from locked chest at " .. minetest.pos_to_string(pos)) - end, - on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) - local meta = minetest.get_meta(pos) - if has_locked_chest_privilege(meta, clicker) then - minetest.show_formspec( - clicker:get_player_name(), - "default:chest_locked", - get_locked_chest_formspec(pos) - ) - end - return itemstack - end, - on_blast = function() end, - on_key_use = function(pos, player) - local secret = minetest.get_meta(pos):get_string("key_lock_secret") - local itemstack = player:get_wielded_item() - local key_meta = minetest.parse_json(itemstack:get_metadata()) - - if secret ~= key_meta.secret then - return - end - - minetest.show_formspec( - player:get_player_name(), - "default:chest_locked", - get_locked_chest_formspec(pos) - ) - end, - on_skeleton_key_use = function(pos, player, newsecret) - local meta = minetest.get_meta(pos) - local owner = meta:get_string("owner") - local name = player:get_player_name() - - -- verify placer is owner of lockable chest - if owner ~= name then - minetest.record_protection_violation(pos, name) - minetest.chat_send_player(name, "You do not own this chest.") - return nil - end - - local secret = meta:get_string("key_lock_secret") - if secret == "" then - secret = newsecret - meta:set_string("key_lock_secret", secret) - end - - return secret, "a locked chest", owner - end, + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = {choppy = 2, oddly_breakable_by_hand = 2}, }) +default.register_chest("chest_locked", { + description = "Locked Chest", + tiles = { + "default_chest_top.png", + "default_chest_top.png", + "default_chest_side.png", + "default_chest_side.png", + "default_chest_lock.png", + "default_chest_inside.png" + }, + sounds = default.node_sound_wood_defaults(), + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = {choppy = 2, oddly_breakable_by_hand = 2}, + protected = true, +}) local bookshelf_formspec = "size[8,7;]" .. @@ -2003,7 +2264,7 @@ default.register_fence("default:fence_acacia_wood", { }) default.register_fence("default:fence_junglewood", { - description = "Junglewood Fence", + description = "Jungle Wood Fence", texture = "default_fence_junglewood.png", inventory_image = "default_fence_overlay.png^default_junglewood.png^default_fence_overlay.png^[makealpha:255,126,126", wield_image = "default_fence_overlay.png^default_junglewood.png^default_fence_overlay.png^[makealpha:255,126,126", @@ -2037,6 +2298,7 @@ minetest.register_node("default:glass", { drawtype = "glasslike_framed_optional", tiles = {"default_glass.png", "default_glass_detail.png"}, paramtype = "light", + paramtype2 = "glasslikeliquidlevel", sunlight_propagates = true, is_ground_content = false, groups = {cracky = 3, oddly_breakable_by_hand = 3}, @@ -2048,6 +2310,7 @@ minetest.register_node("default:obsidian_glass", { drawtype = "glasslike_framed_optional", tiles = {"default_obsidian_glass.png", "default_obsidian_glass_detail.png"}, paramtype = "light", + paramtype2 = "glasslikeliquidlevel", is_ground_content = false, sunlight_propagates = true, sounds = default.node_sound_glass_defaults(), @@ -2078,6 +2341,27 @@ minetest.register_node("default:meselamp", { light_source = default.LIGHT_MAX, }) +minetest.register_node("default:mese_post_light", { + description = "Mese Post Light", + tiles = {"default_mese_post_light_top.png", "default_mese_post_light_top.png", + "default_mese_post_light_side_dark.png", "default_mese_post_light_side_dark.png", + "default_mese_post_light_side.png", "default_mese_post_light_side.png"}, + wield_image = "default_mese_post_light_side.png", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-2 / 16, -8 / 16, -2 / 16, 2 / 16, 8 / 16, 2 / 16}, + }, + }, + paramtype = "light", + light_source = default.LIGHT_MAX, + sunlight_propagates = true, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults(), +}) + -- -- Misc -- @@ -2089,3 +2373,69 @@ minetest.register_node("default:cloud", { sounds = default.node_sound_defaults(), groups = {not_in_creative_inventory = 1}, }) + +-- +-- register trees for leafdecay +-- + +if minetest.get_mapgen_setting("mg_name") == "v6" then + default.register_leafdecay({ + trunks = {"default:tree"}, + leaves = {"default:apple", "default:leaves"}, + radius = 2, + }) + + default.register_leafdecay({ + trunks = {"default:jungletree"}, + leaves = {"default:jungleleaves"}, + radius = 3, + }) + + default.register_leafdecay({ + trunks = {"default:pine_tree"}, + leaves = {"default:pine_needles"}, + radius = 3, + }) +else + default.register_leafdecay({ + trunks = {"default:tree"}, + leaves = {"default:apple", "default:leaves"}, + radius = 3, + }) + + default.register_leafdecay({ + trunks = {"default:jungletree"}, + leaves = {"default:jungleleaves"}, + radius = 2, + }) + + default.register_leafdecay({ + trunks = {"default:pine_tree"}, + leaves = {"default:pine_needles"}, + radius = 2, + }) +end + +default.register_leafdecay({ + trunks = {"default:acacia_tree"}, + leaves = {"default:acacia_leaves"}, + radius = 2, +}) + +default.register_leafdecay({ + trunks = {"default:aspen_tree"}, + leaves = {"default:aspen_leaves"}, + radius = 3, +}) + +default.register_leafdecay({ + trunks = {"default:bush_stem"}, + leaves = {"default:bush_leaves"}, + radius = 1, +}) + +default.register_leafdecay({ + trunks = {"default:acacia_bush_stem"}, + leaves = {"default:acacia_bush_leaves"}, + radius = 1, +}) diff --git a/mods/default/player.lua b/mods/default/player.lua index fd7341f4..0a2078d6 100644 --- a/mods/default/player.lua +++ b/mods/default/player.lua @@ -95,10 +95,6 @@ minetest.register_on_joinplayer(function(player) default.player_set_model(player, "character.b3d") player:set_local_animation({x=0, y=79}, {x=168, y=187}, {x=189, y=198}, {x=200, y=219}, 30) - -- set GUI - if not minetest.setting_getbool("creative_mode") then - player:set_inventory_formspec(default.gui_survival_form) - end player:hud_set_hotbar_image("gui_hotbar.png") player:hud_set_hotbar_selected_image("gui_hotbar_selected.png") end) diff --git a/mods/default/schematics/acacia_log.mts b/mods/default/schematics/acacia_log.mts new file mode 100644 index 00000000..037bca8c Binary files /dev/null and b/mods/default/schematics/acacia_log.mts differ diff --git a/mods/default/schematics/apple_log.mts b/mods/default/schematics/apple_log.mts new file mode 100644 index 00000000..e7ee8f2b Binary files /dev/null and b/mods/default/schematics/apple_log.mts differ diff --git a/mods/default/schematics/apple_tree.mts b/mods/default/schematics/apple_tree.mts index ac09b466..2bd57c1f 100644 Binary files a/mods/default/schematics/apple_tree.mts and b/mods/default/schematics/apple_tree.mts differ diff --git a/mods/default/schematics/apple_tree_from_sapling.mts b/mods/default/schematics/apple_tree_from_sapling.mts index 5d35a154..d258ab1a 100644 Binary files a/mods/default/schematics/apple_tree_from_sapling.mts and b/mods/default/schematics/apple_tree_from_sapling.mts differ diff --git a/mods/default/schematics/aspen_log.mts b/mods/default/schematics/aspen_log.mts new file mode 100644 index 00000000..180e6fd1 Binary files /dev/null and b/mods/default/schematics/aspen_log.mts differ diff --git a/mods/default/schematics/aspen_tree.mts b/mods/default/schematics/aspen_tree.mts index 724aae08..429a831c 100644 Binary files a/mods/default/schematics/aspen_tree.mts and b/mods/default/schematics/aspen_tree.mts differ diff --git a/mods/default/schematics/aspen_tree_from_sapling.mts b/mods/default/schematics/aspen_tree_from_sapling.mts index b7ca1619..b7ab3ee6 100644 Binary files a/mods/default/schematics/aspen_tree_from_sapling.mts and b/mods/default/schematics/aspen_tree_from_sapling.mts differ diff --git a/mods/default/schematics/jungle_log.mts b/mods/default/schematics/jungle_log.mts new file mode 100644 index 00000000..54fa16d1 Binary files /dev/null and b/mods/default/schematics/jungle_log.mts differ diff --git a/mods/default/schematics/jungle_tree.mts b/mods/default/schematics/jungle_tree.mts index 329364a8..01a1b11a 100644 Binary files a/mods/default/schematics/jungle_tree.mts and b/mods/default/schematics/jungle_tree.mts differ diff --git a/mods/default/schematics/jungle_tree_from_sapling.mts b/mods/default/schematics/jungle_tree_from_sapling.mts index babaa45f..f93f0141 100644 Binary files a/mods/default/schematics/jungle_tree_from_sapling.mts and b/mods/default/schematics/jungle_tree_from_sapling.mts differ diff --git a/mods/default/schematics/pine_log.mts b/mods/default/schematics/pine_log.mts new file mode 100644 index 00000000..744c38b0 Binary files /dev/null and b/mods/default/schematics/pine_log.mts differ diff --git a/mods/default/schematics/pine_tree.mts b/mods/default/schematics/pine_tree.mts index 3a3fa7ad..6f27d839 100644 Binary files a/mods/default/schematics/pine_tree.mts and b/mods/default/schematics/pine_tree.mts differ diff --git a/mods/default/schematics/pine_tree_from_sapling.mts b/mods/default/schematics/pine_tree_from_sapling.mts index 629c5da0..e42a9965 100644 Binary files a/mods/default/schematics/pine_tree_from_sapling.mts and b/mods/default/schematics/pine_tree_from_sapling.mts differ diff --git a/mods/default/sounds/default_chest_close.ogg b/mods/default/sounds/default_chest_close.ogg new file mode 100644 index 00000000..53ff23d2 Binary files /dev/null and b/mods/default/sounds/default_chest_close.ogg differ diff --git a/mods/default/sounds/default_chest_open.ogg b/mods/default/sounds/default_chest_open.ogg new file mode 100644 index 00000000..c73c072c Binary files /dev/null and b/mods/default/sounds/default_chest_open.ogg differ diff --git a/mods/default/textures/default_acacia_bush_sapling.png b/mods/default/textures/default_acacia_bush_sapling.png new file mode 100644 index 00000000..940b3aac Binary files /dev/null and b/mods/default/textures/default_acacia_bush_sapling.png differ diff --git a/mods/default/textures/default_aspen_leaves.png b/mods/default/textures/default_aspen_leaves.png index 17a708d1..73064237 100644 Binary files a/mods/default/textures/default_aspen_leaves.png and b/mods/default/textures/default_aspen_leaves.png differ diff --git a/mods/default/textures/default_book.png b/mods/default/textures/default_book.png index 15af2b69..448a7df0 100644 Binary files a/mods/default/textures/default_book.png and b/mods/default/textures/default_book.png differ diff --git a/mods/default/textures/default_book_written.png b/mods/default/textures/default_book_written.png index d843e5f6..9196ac64 100644 Binary files a/mods/default/textures/default_book_written.png and b/mods/default/textures/default_book_written.png differ diff --git a/mods/default/textures/default_bookshelf_slot.png b/mods/default/textures/default_bookshelf_slot.png index 31c4eb5e..715a3dce 100644 Binary files a/mods/default/textures/default_bookshelf_slot.png and b/mods/default/textures/default_bookshelf_slot.png differ diff --git a/mods/default/textures/default_bush_sapling.png b/mods/default/textures/default_bush_sapling.png new file mode 100644 index 00000000..905ba4b8 Binary files /dev/null and b/mods/default/textures/default_bush_sapling.png differ diff --git a/mods/default/textures/default_chest_inside.png b/mods/default/textures/default_chest_inside.png new file mode 100644 index 00000000..5f7b6b13 Binary files /dev/null and b/mods/default/textures/default_chest_inside.png differ diff --git a/mods/default/textures/default_chest_top.png b/mods/default/textures/default_chest_top.png index f1a5cb59..f4a92ee0 100644 Binary files a/mods/default/textures/default_chest_top.png and b/mods/default/textures/default_chest_top.png differ diff --git a/mods/default/textures/default_desert_sandstone.png b/mods/default/textures/default_desert_sandstone.png new file mode 100644 index 00000000..52e445fa Binary files /dev/null and b/mods/default/textures/default_desert_sandstone.png differ diff --git a/mods/default/textures/default_desert_sandstone_block.png b/mods/default/textures/default_desert_sandstone_block.png new file mode 100644 index 00000000..8fc54e75 Binary files /dev/null and b/mods/default/textures/default_desert_sandstone_block.png differ diff --git a/mods/default/textures/default_desert_sandstone_brick.png b/mods/default/textures/default_desert_sandstone_brick.png new file mode 100644 index 00000000..ab58db52 Binary files /dev/null and b/mods/default/textures/default_desert_sandstone_brick.png differ diff --git a/mods/default/textures/default_flint.png b/mods/default/textures/default_flint.png index 3211db15..226c7406 100644 Binary files a/mods/default/textures/default_flint.png and b/mods/default/textures/default_flint.png differ diff --git a/mods/default/textures/default_grass_1.png b/mods/default/textures/default_grass_1.png index 5ed8388b..e9faa2c3 100644 Binary files a/mods/default/textures/default_grass_1.png and b/mods/default/textures/default_grass_1.png differ diff --git a/mods/default/textures/default_grass_2.png b/mods/default/textures/default_grass_2.png index 0ffa8fc2..03729a00 100644 Binary files a/mods/default/textures/default_grass_2.png and b/mods/default/textures/default_grass_2.png differ diff --git a/mods/default/textures/default_grass_3.png b/mods/default/textures/default_grass_3.png index 101fefaa..92ca1b5d 100644 Binary files a/mods/default/textures/default_grass_3.png and b/mods/default/textures/default_grass_3.png differ diff --git a/mods/default/textures/default_grass_4.png b/mods/default/textures/default_grass_4.png index 72c721af..c782a33b 100644 Binary files a/mods/default/textures/default_grass_4.png and b/mods/default/textures/default_grass_4.png differ diff --git a/mods/default/textures/default_grass_5.png b/mods/default/textures/default_grass_5.png index 7fd68388..b727e9cf 100644 Binary files a/mods/default/textures/default_grass_5.png and b/mods/default/textures/default_grass_5.png differ diff --git a/mods/default/textures/default_key.png b/mods/default/textures/default_key.png index d59bfb6b..783d3139 100644 Binary files a/mods/default/textures/default_key.png and b/mods/default/textures/default_key.png differ diff --git a/mods/default/textures/default_key_skeleton.png b/mods/default/textures/default_key_skeleton.png index eafcc195..2b3497d3 100644 Binary files a/mods/default/textures/default_key_skeleton.png and b/mods/default/textures/default_key_skeleton.png differ diff --git a/mods/default/textures/default_ladder_steel.png b/mods/default/textures/default_ladder_steel.png index 1cc6dfde..a312f3e8 100644 Binary files a/mods/default/textures/default_ladder_steel.png and b/mods/default/textures/default_ladder_steel.png differ diff --git a/mods/default/textures/default_mese_post_light_side.png b/mods/default/textures/default_mese_post_light_side.png new file mode 100644 index 00000000..c23b551a Binary files /dev/null and b/mods/default/textures/default_mese_post_light_side.png differ diff --git a/mods/default/textures/default_mese_post_light_side_dark.png b/mods/default/textures/default_mese_post_light_side_dark.png new file mode 100644 index 00000000..c4fc7cea Binary files /dev/null and b/mods/default/textures/default_mese_post_light_side_dark.png differ diff --git a/mods/default/textures/default_mese_post_light_top.png b/mods/default/textures/default_mese_post_light_top.png new file mode 100644 index 00000000..6834bd36 Binary files /dev/null and b/mods/default/textures/default_mese_post_light_top.png differ diff --git a/mods/default/textures/default_mineral_tin.png b/mods/default/textures/default_mineral_tin.png new file mode 100644 index 00000000..232d4b53 Binary files /dev/null and b/mods/default/textures/default_mineral_tin.png differ diff --git a/mods/default/textures/default_rainforest_litter.png b/mods/default/textures/default_rainforest_litter.png new file mode 100644 index 00000000..d762deb4 Binary files /dev/null and b/mods/default/textures/default_rainforest_litter.png differ diff --git a/mods/default/textures/default_rainforest_litter_side.png b/mods/default/textures/default_rainforest_litter_side.png new file mode 100644 index 00000000..7ccb11de Binary files /dev/null and b/mods/default/textures/default_rainforest_litter_side.png differ diff --git a/mods/default/textures/default_sign_steel.png b/mods/default/textures/default_sign_steel.png index 5705c787..3ca0c59d 100644 Binary files a/mods/default/textures/default_sign_steel.png and b/mods/default/textures/default_sign_steel.png differ diff --git a/mods/default/textures/default_sign_wall_steel.png b/mods/default/textures/default_sign_wall_steel.png index d8d4a5b0..2227477f 100644 Binary files a/mods/default/textures/default_sign_wall_steel.png and b/mods/default/textures/default_sign_wall_steel.png differ diff --git a/mods/default/textures/default_sign_wall_wood.png b/mods/default/textures/default_sign_wall_wood.png index f25a67a8..40552c73 100644 Binary files a/mods/default/textures/default_sign_wall_wood.png and b/mods/default/textures/default_sign_wall_wood.png differ diff --git a/mods/default/textures/default_sign_wood.png b/mods/default/textures/default_sign_wood.png index a25a4c34..d0559dac 100644 Binary files a/mods/default/textures/default_sign_wood.png and b/mods/default/textures/default_sign_wood.png differ diff --git a/mods/default/textures/default_silver_sandstone.png b/mods/default/textures/default_silver_sandstone.png new file mode 100644 index 00000000..eac62cb1 Binary files /dev/null and b/mods/default/textures/default_silver_sandstone.png differ diff --git a/mods/default/textures/default_silver_sandstone_block.png b/mods/default/textures/default_silver_sandstone_block.png new file mode 100644 index 00000000..9997461b Binary files /dev/null and b/mods/default/textures/default_silver_sandstone_block.png differ diff --git a/mods/default/textures/default_silver_sandstone_brick.png b/mods/default/textures/default_silver_sandstone_brick.png new file mode 100644 index 00000000..93d87a57 Binary files /dev/null and b/mods/default/textures/default_silver_sandstone_brick.png differ diff --git a/mods/default/textures/default_snow.png b/mods/default/textures/default_snow.png index 4ac35938..fcbef0e5 100644 Binary files a/mods/default/textures/default_snow.png and b/mods/default/textures/default_snow.png differ diff --git a/mods/default/textures/default_snow_side.png b/mods/default/textures/default_snow_side.png index f95b3af8..03456c84 100644 Binary files a/mods/default/textures/default_snow_side.png and b/mods/default/textures/default_snow_side.png differ diff --git a/mods/default/textures/default_snowball.png b/mods/default/textures/default_snowball.png index e952b79c..3a4dc1f6 100644 Binary files a/mods/default/textures/default_snowball.png and b/mods/default/textures/default_snowball.png differ diff --git a/mods/default/textures/default_tin_block.png b/mods/default/textures/default_tin_block.png new file mode 100644 index 00000000..72759b04 Binary files /dev/null and b/mods/default/textures/default_tin_block.png differ diff --git a/mods/default/textures/default_tin_ingot.png b/mods/default/textures/default_tin_ingot.png new file mode 100644 index 00000000..eed53610 Binary files /dev/null and b/mods/default/textures/default_tin_ingot.png differ diff --git a/mods/default/textures/default_tin_lump.png b/mods/default/textures/default_tin_lump.png new file mode 100644 index 00000000..72bd339b Binary files /dev/null and b/mods/default/textures/default_tin_lump.png differ diff --git a/mods/default/tools.lua b/mods/default/tools.lua index 9147f9b3..45c779f1 100644 --- a/mods/default/tools.lua +++ b/mods/default/tools.lua @@ -379,59 +379,26 @@ minetest.register_tool("default:sword_diamond", { sound = {breaks = "default_tool_breaks"}, }) -minetest.register_tool("default:skeleton_key", { - description = "Skeleton Key", - inventory_image = "default_key_skeleton.png", - groups = {key = 1}, - on_place = function(itemstack, placer, pointed_thing) - if pointed_thing.type ~= "node" then - return itemstack - end - - local pos = pointed_thing.under - local node = minetest.get_node(pos) - - if not node then - return itemstack - end - - local on_skeleton_key_use = minetest.registered_nodes[node.name].on_skeleton_key_use - if on_skeleton_key_use then - -- make a new key secret in case the node callback needs it - local random = math.random - local newsecret = string.format( - "%04x%04x%04x%04x", - random(2^16) - 1, random(2^16) - 1, - random(2^16) - 1, random(2^16) - 1) - - local secret, _, _ = on_skeleton_key_use(pos, placer, newsecret) - - if secret then - -- finish and return the new key - itemstack:take_item() - itemstack:add_item("default:key") - itemstack:set_metadata(minetest.write_json({ - secret = secret - })) - return itemstack - end - end - return nil - end -}) - minetest.register_tool("default:key", { description = "Key", inventory_image = "default_key.png", groups = {key = 1, not_in_creative_inventory = 1}, stack_max = 1, on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local def = minetest.registered_nodes[node.name] + if def and def.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return def.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end if pointed_thing.type ~= "node" then return itemstack end local pos = pointed_thing.under - local node = minetest.get_node(pos) + node = minetest.get_node(pos) if not node or node.name == "ignore" then return itemstack diff --git a/mods/default/torch.lua b/mods/default/torch.lua index e94c5bd6..3c3ae965 100644 --- a/mods/default/torch.lua +++ b/mods/default/torch.lua @@ -50,7 +50,7 @@ minetest.register_node("default:torch", { sunlight_propagates = true, walkable = false, liquids_pointable = false, - light_source = 13, + light_source = 12, groups = {choppy=2, dig_immediate=3, flammable=1, attached_node=1, torch=1}, drop = "default:torch", selection_box = { @@ -97,7 +97,7 @@ minetest.register_node("default:torch_wall", { paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, - light_source = 13, + light_source = 12, groups = {choppy=2, dig_immediate=3, flammable=1, not_in_creative_inventory=1, attached_node=1, torch=1}, drop = "default:torch", selection_box = { @@ -118,7 +118,7 @@ minetest.register_node("default:torch_ceiling", { paramtype2 = "wallmounted", sunlight_propagates = true, walkable = false, - light_source = 13, + light_source = 12, groups = {choppy=2, dig_immediate=3, flammable=1, not_in_creative_inventory=1, attached_node=1, torch=1}, drop = "default:torch", selection_box = { @@ -144,4 +144,3 @@ minetest.register_lbm({ end end }) - diff --git a/mods/default/trees.lua b/mods/default/trees.lua index 0b95742c..81c9831e 100644 --- a/mods/default/trees.lua +++ b/mods/default/trees.lua @@ -27,8 +27,7 @@ end -- 'is snow nearby' function local function is_snow_nearby(pos) - return minetest.find_node_near(pos, 1, - {"default:snow", "default:snowblock", "default:dirt_with_snow"}) + return minetest.find_node_near(pos, 1, {"group:snowy"}) end @@ -78,6 +77,14 @@ function default.grow_sapling(pos) minetest.log("action", "An aspen sapling grows into a tree at ".. minetest.pos_to_string(pos)) default.grow_new_aspen_tree(pos) + elseif node.name == "default:bush_sapling" then + minetest.log("action", "A bush sapling grows into a bush at ".. + minetest.pos_to_string(pos)) + default.grow_bush(pos) + elseif node.name == "default:acacia_bush_sapling" then + minetest.log("action", "An acacia bush sapling grows into a bush at ".. + minetest.pos_to_string(pos)) + default.grow_acacia_bush(pos) end end @@ -373,7 +380,7 @@ function default.grow_new_apple_tree(pos) local path = minetest.get_modpath("default") .. "/schematics/apple_tree_from_sapling.mts" minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, - path, "0", nil, false) + path, "random", nil, false) end @@ -427,6 +434,29 @@ function default.grow_new_aspen_tree(pos) end +-- Bushes do not need 'from sapling' schematic variants because +-- only the stem node is force-placed in the schematic. + +-- Bush + +function default.grow_bush(pos) + local path = minetest.get_modpath("default") .. + "/schematics/bush.mts" + minetest.place_schematic({x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + path, "0", nil, false) +end + + +-- Acacia bush + +function default.grow_acacia_bush(pos) + local path = minetest.get_modpath("default") .. + "/schematics/acacia_bush.mts" + minetest.place_schematic({x = pos.x - 1, y = pos.y - 1, z = pos.z - 1}, + path, "0", nil, false) +end + + -- -- Sapling 'on place' function to check protection of node and resulting tree volume -- @@ -458,19 +488,47 @@ function default.sapling_on_place(itemstack, placer, pointed_thing, return itemstack end -- Check tree volume for protection - if not default.intersects_protection( + if default.intersects_protection( vector.add(pos, minp_relative), vector.add(pos, maxp_relative), player_name, interval) then - minetest.set_node(pos, {name = sapling_name}) - if not minetest.setting_getbool("creative_mode") then - itemstack:take_item() - end - else minetest.record_protection_violation(pos, player_name) -- Print extra information to explain minetest.chat_send_player(player_name, "Tree will intersect protection") + return itemstack + end + + minetest.log("action", player_name .. " places node " + .. sapling_name .. " at " .. minetest.pos_to_string(pos)) + + local take_item = not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) + local newnode = {name = sapling_name} + local ndef = minetest.registered_nodes[sapling_name] + minetest.set_node(pos, newnode) + + -- Run callback + if ndef and ndef.after_place_node then + -- Deepcopy place_to and pointed_thing because callback can modify it + if ndef.after_place_node(table.copy(pos), placer, + itemstack, table.copy(pointed_thing)) then + take_item = false + end + end + + -- Run script hook + for _, callback in ipairs(minetest.registered_on_placenodes) do + -- Deepcopy pos, node and pointed_thing because callback can modify them + if callback(table.copy(pos), table.copy(newnode), + placer, table.copy(node or {}), + itemstack, table.copy(pointed_thing)) then + take_item = false + end + end + + if take_item then + itemstack:take_item() end return itemstack diff --git a/mods/doors/init.lua b/mods/doors/init.lua index c5d4a140..371b43a2 100644 --- a/mods/doors/init.lua +++ b/mods/doors/init.lua @@ -6,6 +6,15 @@ local _doors = {} _doors.registered_doors = {} _doors.registered_trapdoors = {} +local function replace_old_owner_information(pos) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("doors_owner") + if owner and owner ~= "" then + meta:set_string("owner", owner) + meta:set_string("doors_owner", "") + end +end + -- returns an object to a door object or nil function doors.get(pos) local node_name = minetest.get_node(pos).name @@ -82,7 +91,7 @@ minetest.register_node("doors:hidden", { on_blast = function() end, tiles = {"doors_blank.png"}, -- 1px transparent block inside door hinge near node top. - nodebox = { + node_box = { type = "fixed", fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32}, }, @@ -139,22 +148,10 @@ function _doors.door_toggle(pos, node, clicker) state = tonumber(state) end - if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then - -- is player wielding the right key? - local item = clicker:get_wielded_item() - local owner = meta:get_string("doors_owner") - if item:get_name() == "default:key" then - local key_meta = minetest.parse_json(item:get_metadata()) - local secret = meta:get_string("key_lock_secret") - if secret ~= key_meta.secret then - return false - end + replace_old_owner_information(pos) - elseif owner ~= "" then - if clicker:get_player_name() ~= owner then - return false - end - end + if clicker and not default.can_interact_with_node(clicker, pos) then + return false end -- until Lua-5.2 we have no bitwise operators :( @@ -205,11 +202,13 @@ local function on_place_node(place_to, newnode, end local function can_dig_door(pos, digger) - local digger_name = digger and digger:get_player_name() - if digger_name and minetest.get_player_privs(digger_name).protection_bypass then + replace_old_owner_information(pos) + if default.can_interact_with_node(digger, pos) then return true + else + minetest.record_protection_violation(pos, digger:get_player_name()) + return false end - return minetest.get_meta(pos):get_string("doors_owner") == digger_name end function doors.register(name, def) @@ -255,6 +254,7 @@ function doors.register(name, def) minetest.register_craftitem(":" .. name, { description = def.description, inventory_image = def.inventory_image, + groups = table.copy(def.groups), on_place = function(itemstack, placer, pointed_thing) local pos @@ -265,7 +265,8 @@ function doors.register(name, def) local node = minetest.get_node(pointed_thing.under) local pdef = minetest.registered_nodes[node.name] - if pdef and pdef.on_rightclick then + if pdef and pdef.on_rightclick and + not placer:get_player_control().sneak then return pdef.on_rightclick(pointed_thing.under, node, placer, itemstack, pointed_thing) end @@ -323,14 +324,16 @@ function doors.register(name, def) meta:set_int("state", state) if def.protected then - meta:set_string("doors_owner", pn) + meta:set_string("owner", pn) meta:set_string("infotext", "Owned by " .. pn) end - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for and creative.is_enabled_for(pn)) then itemstack:take_item() end + minetest.sound_play(def.sounds.place, {pos = pos}) + on_place_node(pos, minetest.get_node(pos), placer, node, itemstack, pointed_thing) @@ -375,7 +378,9 @@ function doors.register(name, def) minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) minetest.check_for_falling({x = pos.x, y = pos.y + 1, z = pos.z}) end - def.on_rotate = false + def.on_rotate = function(pos, node, user, mode, new_param2) + return false + end if def.protected then def.can_dig = can_dig_door @@ -385,8 +390,9 @@ function doors.register(name, def) door:toggle(player) end def.on_skeleton_key_use = function(pos, player, newsecret) + replace_old_owner_information(pos) local meta = minetest.get_meta(pos) - local owner = meta:get_string("doors_owner") + local owner = meta:get_string("owner") local pname = player:get_player_name() -- verify placer is owner of lockable door @@ -523,23 +529,11 @@ end function _doors.trapdoor_toggle(pos, node, clicker) node = node or minetest.get_node(pos) - if clicker and not minetest.check_player_privs(clicker, "protection_bypass") then - -- is player wielding the right key? - local item = clicker:get_wielded_item() - local meta = minetest.get_meta(pos) - local owner = meta:get_string("doors_owner") - if item:get_name() == "default:key" then - local key_meta = minetest.parse_json(item:get_metadata()) - local secret = meta:get_string("key_lock_secret") - if secret ~= key_meta.secret then - return false - end - elseif owner ~= "" then - if clicker:get_player_name() ~= owner then - return false - end - end + replace_old_owner_information(pos) + + if clicker and not default.can_interact_with_node(clicker, pos) then + return false end local def = minetest.registered_nodes[node.name] @@ -581,10 +575,10 @@ function doors.register_trapdoor(name, def) def.after_place_node = function(pos, placer, itemstack, pointed_thing) local pn = placer:get_player_name() local meta = minetest.get_meta(pos) - meta:set_string("doors_owner", pn) + meta:set_string("owner", pn) meta:set_string("infotext", "Owned by "..pn) - return minetest.setting_getbool("creative_mode") + return (creative and creative.is_enabled_for and creative.is_enabled_for(pn)) end def.on_blast = function() end @@ -593,8 +587,9 @@ function doors.register_trapdoor(name, def) door:toggle(player) end def.on_skeleton_key_use = function(pos, player, newsecret) + replace_old_owner_information(pos) local meta = minetest.get_meta(pos) - local owner = meta:get_string("doors_owner") + local owner = meta:get_string("owner") local pname = player:get_player_name() -- verify placer is owner of lockable door @@ -792,7 +787,7 @@ doors.register_fencegate("doors:gate_acacia_wood", { }) doors.register_fencegate("doors:gate_junglewood", { - description = "Junglewood Fence Gate", + description = "Jungle Wood Fence Gate", texture = "default_junglewood.png", material = "default:junglewood", groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} diff --git a/mods/doors/textures/doors_door_glass.png b/mods/doors/textures/doors_door_glass.png index f597299b..26c427b9 100644 Binary files a/mods/doors/textures/doors_door_glass.png and b/mods/doors/textures/doors_door_glass.png differ diff --git a/mods/doors/textures/doors_door_obsidian_glass.png b/mods/doors/textures/doors_door_obsidian_glass.png index 107a5a1a..07ac5b20 100644 Binary files a/mods/doors/textures/doors_door_obsidian_glass.png and b/mods/doors/textures/doors_door_obsidian_glass.png differ diff --git a/mods/dye/init.lua b/mods/dye/init.lua index d414d77c..80284576 100644 --- a/mods/dye/init.lua +++ b/mods/dye/init.lua @@ -74,36 +74,39 @@ minetest.register_craft({ }) -- Mix recipes --- Just mix everything to everything somehow sanely - -local mixbases = {"pink", "magenta", "red", "orange", "brown", "yellow", "green", "dark_green", "cyan", "blue", "violet", "black", "dark_grey", "grey", "white"} - -local mixes = { - -- pink, magenta, red, orange, brown, yellow, green, dark_green, cyan, blue, violet, black, dark_grey, grey, white - white = {"pink", "pink", "pink", "orange", "orange", "yellow", "green", "green", "grey", "cyan", "violet","grey", "grey", "grey","white"}, - grey = {"pink", "pink", "pink", "orange", "orange", "yellow", "green", "green", "grey", "cyan", "violet","dark_grey","grey", "grey"}, - dark_grey = {"brown", "brown", "brown", "brown", "brown", "brown", "dark_green","dark_green","blue", "blue", "violet","black", "dark_grey"}, - black = {"black", "black", "black", "black", "black", "black", "black", "black", "black","black", "black", "black"}, - violet = {"magenta","magenta","magenta","red", "brown", "red", "cyan", "brown", "blue", "violet","violet"}, - blue = {"violet", "violet", "magenta","brown", "brown", "dark_green","cyan", "cyan", "cyan", "blue"}, - cyan = {"brown", "blue", "brown", "dark_green","dark_grey", "green", "cyan", "dark_green","cyan"}, - dark_green = {"brown", "brown", "brown", "brown", "brown", "green", "green", "dark_green"}, - green = {"yellow", "brown", "yellow", "yellow", "dark_green","green", "green"}, - yellow = {"orange", "red", "orange", "yellow", "orange", "yellow"}, - brown = {"brown", "brown", "brown", "orange", "brown"}, - orange = {"orange", "red", "orange", "orange"}, - red = {"pink", "magenta","red"}, - magenta = {"magenta","magenta"}, - pink = {"pink"}, +local dye_recipes = { + -- src1, src2, dst + -- RYB mixes + {"red", "blue", "violet"}, -- "purple" + {"yellow", "red", "orange"}, + {"yellow", "blue", "green"}, + -- RYB complementary mixes + {"yellow", "violet", "dark_grey"}, + {"blue", "orange", "dark_grey"}, + -- CMY mixes - approximation + {"cyan", "yellow", "green"}, + {"cyan", "magenta", "blue"}, + {"yellow", "magenta", "red"}, + -- other mixes that result in a color we have + {"red", "green", "brown"}, + {"magenta", "blue", "violet"}, + {"green", "blue", "cyan"}, + {"pink", "violet", "magenta"}, + -- mixes with black + {"white", "black", "grey"}, + {"grey", "black", "dark_grey"}, + {"green", "black", "dark_green"}, + {"orange", "black", "brown"}, + -- mixes with white + {"white", "red", "pink"}, + {"white", "dark_grey", "grey"}, + {"white", "dark_green", "green"}, } -for one, results in pairs(mixes) do - for i, result in ipairs(results) do - local another = mixbases[i] - minetest.register_craft({ - type = "shapeless", - output = 'dye:' .. result .. ' 2', - recipe = {'dye:' .. one, 'dye:' .. another}, - }) - end +for _, mix in pairs(dye_recipes) do + minetest.register_craft({ + type = "shapeless", + output = 'dye:' .. mix[3] .. ' 2', + recipe = {'dye:' .. mix[1], 'dye:' .. mix[2]}, + }) end diff --git a/mods/farming/api.lua b/mods/farming/api.lua index 182e1b20..35a77e9f 100644 --- a/mods/farming/api.lua +++ b/mods/farming/api.lua @@ -57,7 +57,8 @@ farming.hoe_on_use = function(itemstack, user, pointed_thing, uses) gain = 0.5, }) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(user:get_player_name())) then -- wear tool local wdef = itemstack:get_definition() itemstack:add_wear(65535/(uses-1)) @@ -187,7 +188,8 @@ farming.place_seed = function(itemstack, placer, pointed_thing, plantname) -- add the node and remove 1 item from the itemstack minetest.add_node(pt.above, {name = plantname, param2 = 1}) tick(pt.above) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then itemstack:take_item() end return itemstack @@ -313,6 +315,15 @@ farming.register_plant = function(name, def) }), on_place = function(itemstack, placer, pointed_thing) + local under = pointed_thing.under + local node = minetest.get_node(under) + local udef = minetest.registered_nodes[node.name] + if udef and udef.on_rightclick and + not (placer and placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + return farming.place_seed(itemstack, placer, pointed_thing, mname .. ":seed_" .. pname) end, next_plant = mname .. ":" .. pname .. "_1", @@ -330,12 +341,16 @@ farming.register_plant = function(name, def) -- Register growing steps for i = 1, def.steps do + local base_rarity = 1 + if def.steps ~= 1 then + base_rarity = 8 - (i - 1) * 7 / (def.steps - 1) + end local drop = { items = { - {items = {mname .. ":" .. pname}, rarity = 9 - i}, - {items = {mname .. ":" .. pname}, rarity= 18 - i * 2}, - {items = {mname .. ":seed_" .. pname}, rarity = 9 - i}, - {items = {mname .. ":seed_" .. pname}, rarity = 18 - i * 2}, + {items = {mname .. ":" .. pname}, rarity = base_rarity}, + {items = {mname .. ":" .. pname}, rarity = base_rarity * 2}, + {items = {mname .. ":seed_" .. pname}, rarity = base_rarity}, + {items = {mname .. ":seed_" .. pname}, rarity = base_rarity * 2}, } } local nodegroups = {snappy = 3, flammable = 2, plant = 1, not_in_creative_inventory = 1, attached_node = 1} diff --git a/mods/farming/nodes.lua b/mods/farming/nodes.lua index 09ad36f5..c969d31b 100644 --- a/mods/farming/nodes.lua +++ b/mods/farming/nodes.lua @@ -22,6 +22,14 @@ minetest.override_item("default:dirt_with_dry_grass", { } }) +minetest.override_item("default:dirt_with_rainforest_litter", { + soil = { + base = "default:dirt_with_rainforest_litter", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + minetest.register_node("farming:soil", { description = "Soil", tiles = {"default_dirt.png^farming_soil.png", "default_dirt.png"}, diff --git a/mods/fire/init.lua b/mods/fire/init.lua index bee487a5..f97636b5 100644 --- a/mods/fire/init.lua +++ b/mods/fire/init.lua @@ -24,7 +24,7 @@ minetest.register_node("fire:basic_flame", { }, inventory_image = "fire_basic_flame.png", paramtype = "light", - light_source = 14, + light_source = 13, walkable = false, buildable_to = true, sunlight_propagates = true, @@ -44,9 +44,6 @@ minetest.register_node("fire:basic_flame", { on_construct = function(pos) minetest.get_node_timer(pos):start(math.random(30, 60)) end, - - on_blast = function() -- Unaffected by explosions - end, }) minetest.register_node("fire:permanent_flame", { @@ -65,16 +62,13 @@ minetest.register_node("fire:permanent_flame", { }, inventory_image = "fire_basic_flame.png", paramtype = "light", - light_source = 14, + light_source = 13, walkable = false, buildable_to = true, sunlight_propagates = true, damage_per_second = 4, groups = {igniter = 2, dig_immediate = 3}, drop = "", - - on_blast = function() -- Unaffected by explosions - end, }) @@ -86,36 +80,37 @@ minetest.register_tool("fire:flint_and_steel", { sound = {breaks = "default_tool_breaks"}, on_use = function(itemstack, user, pointed_thing) - local pt = pointed_thing + local sound_pos = pointed_thing.above or user:get_pos() minetest.sound_play( "fire_flint_and_steel", - {pos = pt.above, gain = 0.5, max_hear_distance = 8} + {pos = sound_pos, gain = 0.5, max_hear_distance = 8} ) - if pt.type == "node" then - local node_under = minetest.get_node(pt.under).name + local player_name = user:get_player_name() + if pointed_thing.type == "node" then + local node_under = minetest.get_node(pointed_thing.under).name local nodedef = minetest.registered_nodes[node_under] if not nodedef then return end - local player_name = user:get_player_name() - if minetest.is_protected(pt.under, player_name) then + if minetest.is_protected(pointed_thing.under, player_name) then minetest.chat_send_player(player_name, "This area is protected") return end if nodedef.on_ignite then - nodedef.on_ignite(pt.under, user) + nodedef.on_ignite(pointed_thing.under, user) elseif minetest.get_item_group(node_under, "flammable") >= 1 - and minetest.get_node(pt.above).name == "air" then - minetest.set_node(pt.above, {name = "fire:basic_flame"}) + and minetest.get_node(pointed_thing.above).name == "air" then + minetest.set_node(pointed_thing.above, {name = "fire:basic_flame"}) end end - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then -- Wear tool local wdef = itemstack:get_definition() itemstack:add_wear(1000) -- Tool break sound if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then - minetest.sound_play(wdef.sound.breaks, {pos = pt.above, gain = 0.5}) + minetest.sound_play(wdef.sound.breaks, {pos = sound_pos, gain = 0.5}) end return itemstack end @@ -153,7 +148,7 @@ minetest.override_item("default:coalblock", { -- Sound -- -local flame_sound = minetest.setting_getbool("flame_sound") +local flame_sound = minetest.settings:get_bool("flame_sound") if flame_sound == nil then -- Enable if no setting present flame_sound = true @@ -295,11 +290,16 @@ minetest.register_abm({ -- Enable the following ABMs according to 'enable fire' setting -local fire_enabled = minetest.setting_getbool("enable_fire") +local fire_enabled = minetest.settings:get_bool("enable_fire") if fire_enabled == nil then - -- New setting not specified, check for old setting. - -- If old setting is also not specified, 'not nil' is true. - fire_enabled = not minetest.setting_getbool("disable_fire") + -- enable_fire setting not specified, check for disable_fire + local fire_disabled = minetest.settings:get_bool("disable_fire") + if fire_disabled == nil then + -- Neither setting specified, check whether singleplayer + fire_enabled = minetest.is_singleplayer() + else + fire_enabled = not fire_disabled + end end if not fire_enabled then diff --git a/mods/fire/textures/fire_flint_steel.png b/mods/fire/textures/fire_flint_steel.png index 624f5565..c262ebc0 100644 Binary files a/mods/fire/textures/fire_flint_steel.png and b/mods/fire/textures/fire_flint_steel.png differ diff --git a/mods/flowers/init.lua b/mods/flowers/init.lua index c7cc670e..cb5b2193 100644 --- a/mods/flowers/init.lua +++ b/mods/flowers/init.lua @@ -107,11 +107,16 @@ function flowers.flower_spread(pos, node) pos.y = pos.y - 1 local under = minetest.get_node(pos) pos.y = pos.y + 1 - if under.name == "default:desert_sand" then + -- Replace flora with dry shrub in desert sand and silver sand, + -- as this is the only way to generate them. + -- However, preserve grasses in sand dune biomes. + if minetest.get_item_group(under.name, "sand") == 1 and + under.name ~= "default:sand" then minetest.set_node(pos, {name = "default:dry_shrub"}) return - elseif under.name ~= "default:dirt_with_grass" and - under.name ~= "default:dirt_with_dry_grass" then + end + + if minetest.get_item_group(under.name, "soil") == 0 then return end @@ -126,24 +131,26 @@ function flowers.flower_spread(pos, node) return end - local seedling = minetest.find_nodes_in_area_under_air(pos0, pos1, - {"default:dirt_with_grass", "default:dirt_with_dry_grass"}) - if #seedling > 0 then - seedling = seedling[math.random(#seedling)] - seedling.y = seedling.y + 1 - light = minetest.get_node_light(seedling) - if not light or light < 13 then + local soils = minetest.find_nodes_in_area_under_air( + pos0, pos1, "group:soil") + if #soils > 0 then + local seedling = soils[math.random(#soils)] + local seedling_above = + {x = seedling.x, y = seedling.y + 1, z = seedling.z} + light = minetest.get_node_light(seedling_above) + if not light or light < 13 or + -- Desert sand is in the soil group + minetest.get_node(seedling).name == "default:desert_sand" then return end - minetest.set_node(seedling, {name = node.name}) + + minetest.set_node(seedling_above, {name = node.name}) end end minetest.register_abm({ label = "Flower spread", nodenames = {"group:flora"}, - neighbors = {"default:dirt_with_grass", "default:dirt_with_dry_grass", - "default:desert_sand"}, interval = 13, chance = 96, action = function(...) @@ -264,7 +271,7 @@ minetest.register_node("flowers:waterlily", { node_placement_prediction = "", node_box = { type = "fixed", - fixed = {-0.5, -0.5, -0.5, 0.5, -15 / 32, 0.5} + fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5} }, selection_box = { type = "fixed", @@ -282,7 +289,8 @@ minetest.register_node("flowers:waterlily", { if not minetest.is_protected(pos, player_name) then minetest.set_node(pos, {name = "flowers:waterlily", param2 = math.random(0, 3)}) - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then itemstack:take_item() end else diff --git a/mods/flowers/mapgen.lua b/mods/flowers/mapgen.lua index ec03c9b2..2b960907 100644 --- a/mods/flowers/mapgen.lua +++ b/mods/flowers/mapgen.lua @@ -94,7 +94,8 @@ local function register_flower(seed, name) octaves = 3, persist = 0.6 }, - biomes = {"grassland", "deciduous_forest", "coniferous_forest"}, + biomes = {"grassland", "deciduous_forest", "coniferous_forest", + "floatland_grassland", "floatland_coniferous_forest"}, y_min = 1, y_max = 31000, decoration = "flowers:"..name, @@ -114,7 +115,8 @@ local function register_mushroom(name) octaves = 3, persist = 0.66 }, - biomes = {"deciduous_forest", "coniferous_forest"}, + biomes = {"deciduous_forest", "coniferous_forest", + "floatland_coniferous_forest"}, y_min = 1, y_max = 31000, decoration = "flowers:"..name, diff --git a/mods/flowers/textures/flowers_waterlily.png b/mods/flowers/textures/flowers_waterlily.png index a92d3b9f..305c4458 100644 Binary files a/mods/flowers/textures/flowers_waterlily.png and b/mods/flowers/textures/flowers_waterlily.png differ diff --git a/mods/give_initial_stuff/init.lua b/mods/give_initial_stuff/init.lua index 022b7438..4815bd84 100644 --- a/mods/give_initial_stuff/init.lua +++ b/mods/give_initial_stuff/init.lua @@ -1,4 +1,4 @@ -local stuff_string = minetest.setting_get("initial_stuff") or +local stuff_string = minetest.settings:get("initial_stuff") or "default:pick_steel,default:axe_steel,default:shovel_steel," .. "default:torch 99,default:cobble 99" @@ -39,6 +39,6 @@ function give_initial_stuff.get_list() end give_initial_stuff.add_from_csv(stuff_string) -if minetest.setting_getbool("give_initial_stuff") then +if minetest.settings:get_bool("give_initial_stuff") then minetest.register_on_newplayer(give_initial_stuff.give) end diff --git a/mods/killme/init.lua b/mods/killme/init.lua new file mode 100644 index 00000000..9b674754 --- /dev/null +++ b/mods/killme/init.lua @@ -0,0 +1,24 @@ +minetest.register_chatcommand("killme", { + description = "Kill yourself to respawn", + func = function(name) + local player = minetest.get_player_by_name(name) + if player then + if minetest.settings:get_bool("enable_damage") then + player:set_hp(0) + return true + else + for _, callback in pairs(core.registered_on_respawnplayers) do + if callback(player) then + return true + end + end + + -- There doesn't seem to be a way to get a default spawn pos from the lua API + return false, "No static_spawnpoint defined" + end + else + -- Show error message if used when not logged in, eg: from IRC mod + return false, "You need to be online to be killed!" + end + end +}) diff --git a/mods/nyancat/README.txt b/mods/nyancat/README.txt deleted file mode 100644 index fadc1d23..00000000 --- a/mods/nyancat/README.txt +++ /dev/null @@ -1,16 +0,0 @@ -Minetest Game mod: nyancat -========================== -See license.txt for license information. - -Authors of source code ----------------------- -Originally by celeron55, Perttu Ahola (LGPL 2.1) -Various Minetest developers and contributors (LGPL 2.1) - -Authors of media files ----------------------- -VanessaE (CC BY-SA 3.0): - nyancat_front.png - nyancat_back.png - nyancat_side.png - nyancat_rainbow.png diff --git a/mods/nyancat/depends.txt b/mods/nyancat/depends.txt deleted file mode 100644 index 4ad96d51..00000000 --- a/mods/nyancat/depends.txt +++ /dev/null @@ -1 +0,0 @@ -default diff --git a/mods/nyancat/init.lua b/mods/nyancat/init.lua deleted file mode 100644 index 7192beb8..00000000 --- a/mods/nyancat/init.lua +++ /dev/null @@ -1,89 +0,0 @@ -minetest.register_node("nyancat:nyancat", { - description = "Nyan Cat", - tiles = {"nyancat_side.png", "nyancat_side.png", "nyancat_side.png", - "nyancat_side.png", "nyancat_back.png", "nyancat_front.png"}, - paramtype = "light", - light_source = default.LIGHT_MAX, - paramtype2 = "facedir", - groups = {cracky = 2}, - is_ground_content = false, - legacy_facedir_simple = true, - sounds = default.node_sound_defaults(), -}) - -minetest.register_node("nyancat:nyancat_rainbow", { - description = "Nyan Cat Rainbow", - tiles = { - "nyancat_rainbow.png^[transformR90", - "nyancat_rainbow.png^[transformR90", - "nyancat_rainbow.png" - }, - paramtype = "light", - light_source = default.LIGHT_MAX, - paramtype2 = "facedir", - groups = {cracky = 2}, - is_ground_content = false, - sounds = default.node_sound_defaults(), -}) - -minetest.register_craft({ - type = "fuel", - recipe = "nyancat:nyancat", - burntime = 1, -}) - -minetest.register_craft({ - type = "fuel", - recipe = "nyancat:nyancat_rainbow", - burntime = 1, -}) - -nyancat = {} - -function nyancat.place(pos, facedir, length) - if facedir > 3 then - facedir = 0 - end - local tailvec = minetest.facedir_to_dir(facedir) - local p = {x = pos.x, y = pos.y, z = pos.z} - minetest.set_node(p, {name = "nyancat:nyancat", param2 = facedir}) - for i = 1, length do - p.x = p.x + tailvec.x - p.z = p.z + tailvec.z - minetest.set_node(p, {name = "nyancat:nyancat_rainbow", param2 = facedir}) - end -end - -function nyancat.generate(minp, maxp, seed) - local height_min = -31000 - local height_max = -32 - if maxp.y < height_min or minp.y > height_max then - return - end - local y_min = math.max(minp.y, height_min) - local y_max = math.min(maxp.y, height_max) - local volume = (maxp.x - minp.x + 1) * (y_max - y_min + 1) * (maxp.z - minp.z + 1) - local pr = PseudoRandom(seed + 9324342) - local max_num_nyancats = math.floor(volume / (16 * 16 * 16)) - for i = 1, max_num_nyancats do - if pr:next(0, 1000) == 0 then - local x0 = pr:next(minp.x, maxp.x) - local y0 = pr:next(minp.y, maxp.y) - local z0 = pr:next(minp.z, maxp.z) - local p0 = {x = x0, y = y0, z = z0} - nyancat.place(p0, pr:next(0, 3), pr:next(3, 15)) - end - end -end - -minetest.register_on_generated(function(minp, maxp, seed) - nyancat.generate(minp, maxp, seed) -end) - --- Legacy -minetest.register_alias("default:nyancat", "nyancat:nyancat") -minetest.register_alias("default:nyancat_rainbow", "nyancat:nyancat_rainbow") -minetest.register_alias("nyancat", "nyancat:nyancat") -minetest.register_alias("nyancat_rainbow", "nyancat:nyancat_rainbow") -default.make_nyancat = nyancat.place -default.generate_nyancats = nyancat.generate diff --git a/mods/nyancat/license.txt b/mods/nyancat/license.txt deleted file mode 100644 index 3aa38617..00000000 --- a/mods/nyancat/license.txt +++ /dev/null @@ -1,50 +0,0 @@ -License of source code ----------------------- - -GNU Lesser General Public License, version 2.1 -Copyright (C) 2011-2016 celeron55, Perttu Ahola -Copyright (C) 2012-2016 Various Minetest developers and contributors - -This program is free software; you can redistribute it and/or modify it under the terms -of the GNU Lesser General Public License as published by the Free Software Foundation; -either version 2.1 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 Lesser General Public License for more details: -https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - -Licenses of media (textures) ----------------------------- - -Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) -Copyright (C) 2012-2016 VanessaE - -You are free to: -Share — copy and redistribute the material in any medium or format. -Adapt — remix, transform, and build upon the material for any purpose, even commercially. -The licensor cannot revoke these freedoms as long as you follow the license terms. - -Under the following terms: - -Attribution — You must give appropriate credit, provide a link to the license, and -indicate if changes were made. You may do so in any reasonable manner, but not in any way -that suggests the licensor endorses you or your use. - -ShareAlike — If you remix, transform, or build upon the material, you must distribute -your contributions under the same license as the original. - -No additional restrictions — You may not apply legal terms or technological measures that -legally restrict others from doing anything the license permits. - -Notices: - -You do not have to comply with the license for elements of the material in the public -domain or where your use is permitted by an applicable exception or limitation. -No warranties are given. The license may not give you all of the permissions necessary -for your intended use. For example, other rights such as publicity, privacy, or moral -rights may limit how you use the material. - -For more details: -http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/mods/nyancat/textures/nyancat_back.png b/mods/nyancat/textures/nyancat_back.png deleted file mode 100644 index e479ace8..00000000 Binary files a/mods/nyancat/textures/nyancat_back.png and /dev/null differ diff --git a/mods/nyancat/textures/nyancat_front.png b/mods/nyancat/textures/nyancat_front.png deleted file mode 100644 index c9dd6a33..00000000 Binary files a/mods/nyancat/textures/nyancat_front.png and /dev/null differ diff --git a/mods/nyancat/textures/nyancat_rainbow.png b/mods/nyancat/textures/nyancat_rainbow.png deleted file mode 100644 index 685a22cc..00000000 Binary files a/mods/nyancat/textures/nyancat_rainbow.png and /dev/null differ diff --git a/mods/nyancat/textures/nyancat_side.png b/mods/nyancat/textures/nyancat_side.png deleted file mode 100644 index 3152c337..00000000 Binary files a/mods/nyancat/textures/nyancat_side.png and /dev/null differ diff --git a/mods/screwdriver/init.lua b/mods/screwdriver/init.lua index e73b618f..e76f0545 100644 --- a/mods/screwdriver/init.lua +++ b/mods/screwdriver/init.lua @@ -1,13 +1,5 @@ screwdriver = {} -local function nextrange(x, max) - x = x + 1 - if x > max then - x = 0 - end - return x -end - screwdriver.ROTATE_FACE = 1 screwdriver.ROTATE_AXIS = 2 screwdriver.disallow = function(pos, node, user, mode, new_param2) @@ -19,6 +11,73 @@ screwdriver.rotate_simple = function(pos, node, user, mode, new_param2) end end +-- For attached wallmounted nodes: returns true if rotation is valid +-- simplified version of minetest:builtin/game/falling.lua#L148. +local function check_attached_node(pos, rotation) + local d = minetest.wallmounted_to_dir(rotation) + local p2 = vector.add(pos, d) + local n = minetest.get_node(p2).name + local def2 = minetest.registered_nodes[n] + if def2 and not def2.walkable then + return false + end + return true +end + +screwdriver.rotate = {} + +local facedir_tbl = { + [screwdriver.ROTATE_FACE] = { + [0] = 1, [1] = 2, [2] = 3, [3] = 0, + [4] = 5, [5] = 6, [6] = 7, [7] = 4, + [8] = 9, [9] = 10, [10] = 11, [11] = 8, + [12] = 13, [13] = 14, [14] = 15, [15] = 12, + [16] = 17, [17] = 18, [18] = 19, [19] = 16, + [20] = 21, [21] = 22, [22] = 23, [23] = 20, + }, + [screwdriver.ROTATE_AXIS] = { + [0] = 4, [1] = 4, [2] = 4, [3] = 4, + [4] = 8, [5] = 8, [6] = 8, [7] = 8, + [8] = 12, [9] = 12, [10] = 12, [11] = 12, + [12] = 16, [13] = 16, [14] = 16, [15] = 16, + [16] = 20, [17] = 20, [18] = 20, [19] = 20, + [20] = 0, [21] = 0, [22] = 0, [23] = 0, + }, +} + +screwdriver.rotate.facedir = function(pos, node, mode) + local rotation = node.param2 % 32 -- get first 5 bits + local other = node.param2 - rotation + rotation = facedir_tbl[mode][rotation] or 0 + return rotation + other +end + +screwdriver.rotate.colorfacedir = screwdriver.rotate.facedir + +local wallmounted_tbl = { + [screwdriver.ROTATE_FACE] = {[2] = 5, [3] = 4, [4] = 2, [5] = 3, [1] = 0, [0] = 1}, + [screwdriver.ROTATE_AXIS] = {[2] = 5, [3] = 4, [4] = 2, [5] = 1, [1] = 0, [0] = 3} +} + +screwdriver.rotate.wallmounted = function(pos, node, mode) + local rotation = node.param2 % 8 -- get first 3 bits + local other = node.param2 - rotation + rotation = wallmounted_tbl[mode][rotation] or 0 + if minetest.get_item_group(node.name, "attached_node") ~= 0 then + -- find an acceptable orientation + for i = 1, 5 do + if not check_attached_node(pos, rotation) then + rotation = wallmounted_tbl[mode][rotation] or 0 + else + break + end + end + end + return rotation + other +end + +screwdriver.rotate.colorwallmounted = screwdriver.rotate.wallmounted + -- Handles rotation screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) if pointed_thing.type ~= "node" then @@ -34,54 +93,48 @@ screwdriver.handler = function(itemstack, user, pointed_thing, mode, uses) local node = minetest.get_node(pos) local ndef = minetest.registered_nodes[node.name] - -- verify node is facedir (expected to be rotatable) - if not ndef or ndef.paramtype2 ~= "facedir" then - return + if not ndef then + return itemstack end - -- Compute param2 - local rotationPart = node.param2 % 32 -- get first 4 bits - local preservePart = node.param2 - rotationPart - local axisdir = math.floor(rotationPart / 4) - local rotation = rotationPart - axisdir * 4 - if mode == screwdriver.ROTATE_FACE then - rotationPart = axisdir * 4 + nextrange(rotation, 3) - elseif mode == screwdriver.ROTATE_AXIS then - rotationPart = nextrange(axisdir, 5) * 4 + -- can we rotate this paramtype2? + local fn = screwdriver.rotate[ndef.paramtype2] + if not fn and not ndef.on_rotate then + return itemstack end - local new_param2 = preservePart + rotationPart local should_rotate = true + local new_param2 + if fn then + new_param2 = fn(pos, node, mode) + else + new_param2 = node.param2 + end - if ndef and ndef.on_rotate then -- Node provides a handler, so let the handler decide instead if the node can be rotated + -- Node provides a handler, so let the handler decide instead if the node can be rotated + if ndef.on_rotate then -- Copy pos and node because callback can modify it local result = ndef.on_rotate(vector.new(pos), {name = node.name, param1 = node.param1, param2 = node.param2}, user, mode, new_param2) if result == false then -- Disallow rotation - return + return itemstack elseif result == true then should_rotate = false end - else - if not ndef or not ndef.paramtype2 == "facedir" or - ndef.on_rotate == false or - (ndef.drawtype == "nodebox" and - not ndef.node_box.type == "fixed") or - node.param2 == nil then - return - end - - if ndef.can_dig and not ndef.can_dig(pos, user) then - return - end + elseif ndef.on_rotate == false then + return itemstack + elseif ndef.can_dig and not ndef.can_dig(pos, user) then + return itemstack end - if should_rotate then + if should_rotate and new_param2 ~= node.param2 then node.param2 = new_param2 minetest.swap_node(pos, node) + minetest.check_for_falling(pos) end - if not minetest.setting_getbool("creative_mode") then + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(user:get_player_name())) then itemstack:add_wear(65535 / ((uses or 200) - 1)) end diff --git a/mods/sethome/init.lua b/mods/sethome/init.lua index e0fc453d..13a33e57 100644 --- a/mods/sethome/init.lua +++ b/mods/sethome/init.lua @@ -5,9 +5,9 @@ local homes_file = minetest.get_worldpath() .. "/homes" local homepos = {} local function loadhomes() - local input, err = io.open(homes_file, "r") + local input = io.open(homes_file, "r") if not input then - return minetest.log("info", "Could not load player homes file: " .. err) + return -- no longer an error end -- Iterate over all stored positions in the format "x y z player" for each line @@ -24,11 +24,13 @@ sethome.set = function(name, pos) if not player or not pos then return false end + player:set_attribute("sethome:home", minetest.pos_to_string(pos)) + -- remove `name` from the old storage file local data = {} - local output, err = io.open(homes_file, "w") + local output = io.open(homes_file, "w") if output then - homepos[name] = pos + homepos[name] = nil for i, v in pairs(homepos) do table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, i)) end @@ -36,12 +38,18 @@ sethome.set = function(name, pos) io.close(output) return true end - minetest.log("action", "Unable to write to player homes file: " .. err) - return false + return true -- if the file doesn't exist - don't return an error. end sethome.get = function(name) - local pos = homepos[name] + local player = minetest.get_player_by_name(name) + local pos = minetest.string_to_pos(player:get_attribute("sethome:home")) + if pos then + return pos + end + + -- fetch old entry from storage table + pos = homepos[name] if pos then return vector.new(pos) else @@ -50,9 +58,10 @@ sethome.get = function(name) end sethome.go = function(name) + local pos = sethome.get(name) local player = minetest.get_player_by_name(name) - if player and homepos[name] then - player:setpos(homepos[name]) + if player and pos then + player:setpos(pos) return true end return false diff --git a/mods/sfinv/api.lua b/mods/sfinv/api.lua index 2fef3c84..bd6de1ed 100644 --- a/mods/sfinv/api.lua +++ b/mods/sfinv/api.lua @@ -70,7 +70,7 @@ function sfinv.get_formspec(player, context) nav[#nav + 1] = pdef.title nav_ids[#nav_ids + 1] = pdef.name if pdef.name == context.page then - current_idx = i + current_idx = #nav_ids end end end @@ -91,27 +91,45 @@ function sfinv.get_formspec(player, context) end end -function sfinv.set_player_inventory_formspec(player, context) +function sfinv.get_or_create_context(player) + local name = player:get_player_name() + local context = sfinv.contexts[name] if not context then - local name = player:get_player_name() - context = sfinv.contexts[name] - if not context then - context = { - page = sfinv.get_homepage_name(player) - } - sfinv.contexts[name] = context - end + context = { + page = sfinv.get_homepage_name(player) + } + sfinv.contexts[name] = context end + return context +end - local fs = sfinv.get_formspec(player, context) +function sfinv.set_context(player, context) + sfinv.contexts[player:get_player_name()] = context +end + +function sfinv.set_player_inventory_formspec(player, context) + local fs = sfinv.get_formspec(player, + context or sfinv.get_or_create_context(player)) player:set_inventory_formspec(fs) end +function sfinv.set_page(player, pagename) + local context = sfinv.get_or_create_context(player) + local oldpage = sfinv.pages[context.page] + if oldpage and oldpage.on_leave then + oldpage:on_leave(player, context) + end + context.page = pagename + local page = sfinv.pages[pagename] + if page.on_enter then + page:on_enter(player, context) + end + sfinv.set_player_inventory_formspec(player, context) +end + minetest.register_on_joinplayer(function(player) if sfinv.enabled then - minetest.after(0.5, function() - sfinv.set_player_inventory_formspec(player) - end) + sfinv.set_player_inventory_formspec(player) end end) @@ -132,30 +150,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields) return false end - -- Handle Events + -- Was a tab selected? if fields.tabs and context.nav then local tid = tonumber(fields.tabs) if tid and tid > 0 then local id = context.nav[tid] local page = sfinv.pages[id] if id and page then - local oldpage = sfinv.pages[context.page] - if oldpage and oldpage.on_leave then - oldpage:on_leave(player, context) - end - context.page = id - if page.on_enter then - page:on_enter(player, context) - end - sfinv.set_player_inventory_formspec(player, context) + sfinv.set_page(player, id) end end - return - end - - -- Pass to page - local page = sfinv.pages[context.page] - if page and page.on_player_receive_fields then - return page:on_player_receive_fields(player, context, fields) + else + -- Pass event to page + local page = sfinv.pages[context.page] + if page and page.on_player_receive_fields then + return page:on_player_receive_fields(player, context, fields) + end end end) diff --git a/mods/stairs/init.lua b/mods/stairs/init.lua index 191c78df..90172ef0 100644 --- a/mods/stairs/init.lua +++ b/mods/stairs/init.lua @@ -15,8 +15,32 @@ minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood") -- Get setting for replace ABM -local replace = minetest.setting_getbool("enable_stairs_replace_abm") +local replace = minetest.settings:get_bool("enable_stairs_replace_abm") +local function rotate_and_place(itemstack, placer, pointed_thing) + local p0 = pointed_thing.under + local p1 = pointed_thing.above + local param2 = 0 + + local placer_pos = placer:getpos() + if placer_pos then + param2 = minetest.dir_to_facedir(vector.subtract(p1, placer_pos)) + end + + local finepos = minetest.pointed_thing_to_face_pos(placer, pointed_thing) + local fpos = finepos.y % 1 + + if p0.y - 1 == p1.y or (fpos > 0 and fpos < 0.5) + or (fpos < -0.5 and fpos > -0.999999999) then + param2 = param2 + 20 + if param2 == 21 then + param2 = 23 + elseif param2 == 23 then + param2 = 21 + end + end + return minetest.item_place(itemstack, placer, pointed_thing, param2) +end -- Register stairs. -- Node will be called stairs:stair_ @@ -52,30 +76,7 @@ function stairs.register_stair(subname, recipeitem, groups, images, description, return itemstack end - local p0 = pointed_thing.under - local p1 = pointed_thing.above - local param2 = 0 - - local placer_pos = placer:getpos() - if placer_pos then - local dir = { - x = p1.x - placer_pos.x, - y = p1.y - placer_pos.y, - z = p1.z - placer_pos.z - } - param2 = minetest.dir_to_facedir(dir) - end - - if p0.y - 1 == p1.y then - param2 = param2 + 20 - if param2 == 21 then - param2 = 23 - elseif param2 == 23 then - param2 = 21 - end - end - - return minetest.item_place(itemstack, placer, pointed_thing, param2) + return rotate_and_place(itemstack, placer, pointed_thing) end, }) @@ -126,8 +127,6 @@ end -- Slab facedir to placement 6d matching table local slab_trans_dir = {[0] = 8, 0, 2, 1, 3, 4} --- Slab facedir when placing initial slab against other surface -local slab_trans_dir_place = {[0] = 0, 20, 12, 16, 4, 8} -- Register slabs. -- Node will be called stairs:slab_ @@ -150,8 +149,10 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, on_place = function(itemstack, placer, pointed_thing) local under = minetest.get_node(pointed_thing.under) local wield_item = itemstack:get_name() + local creative_enabled = (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) - if under and wield_item == under.name then + if under and under.name:find("stairs:slab_") then -- place slab using under node orientation local dir = minetest.dir_to_facedir(vector.subtract( pointed_thing.above, pointed_thing.under), true) @@ -159,7 +160,9 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, local p2 = under.param2 -- combine two slabs if possible - if slab_trans_dir[math.floor(p2 / 4)] == dir then + if slab_trans_dir[math.floor(p2 / 4)] == dir + and wield_item == under.name then + if not recipeitem then return itemstack end @@ -171,7 +174,7 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, return end minetest.set_node(pointed_thing.under, {name = recipeitem, param2 = p2}) - if not minetest.setting_getbool("creative_mode") then + if not creative_enabled then itemstack:take_item() end return itemstack @@ -187,21 +190,12 @@ function stairs.register_slab(subname, recipeitem, groups, images, description, -- else attempt to place node with proper param2 minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2) - if not minetest.setting_getbool("creative_mode") then + if not creative_enabled then itemstack:take_item() end return itemstack else - -- place slab using look direction of player - local dir = minetest.dir_to_wallmounted(vector.subtract( - pointed_thing.above, pointed_thing.under), true) - - local rot = slab_trans_dir_place[dir] - if rot == 0 or rot == 20 then - rot = rot + minetest.dir_to_facedir(placer:get_look_dir()) - end - - return minetest.item_place(itemstack, placer, pointed_thing, rot) + return rotate_and_place(itemstack, placer, pointed_thing) end end, }) @@ -444,6 +438,66 @@ stairs.register_stair_and_slab( default.node_sound_stone_defaults() ) +stairs.register_stair_and_slab( + "desert_sandstone", + "default:desert_sandstone", + {crumbly = 1, cracky = 3}, + {"default_desert_sandstone.png"}, + "Desert Sandstone Stair", + "Desert Sandstone Slab", + default.node_sound_stone_defaults() +) + +stairs.register_stair_and_slab( + "desert_sandstone_brick", + "default:desert_sandstone_brick", + {cracky = 2}, + {"default_desert_sandstone_brick.png"}, + "Desert Sandstone Brick Stair", + "Desert Sandstone Brick Slab", + default.node_sound_stone_defaults() +) + +stairs.register_stair_and_slab( + "desert_sandstone_block", + "default:desert_sandstone_block", + {cracky = 2}, + {"default_desert_sandstone_block.png"}, + "Desert Sandstone Block Stair", + "Desert Sandstone Block Slab", + default.node_sound_stone_defaults() +) + +stairs.register_stair_and_slab( + "silver_sandstone", + "default:silver_sandstone", + {crumbly = 1, cracky = 3}, + {"default_silver_sandstone.png"}, + "Silver Sandstone Stair", + "Silver Sandstone Slab", + default.node_sound_stone_defaults() +) + +stairs.register_stair_and_slab( + "silver_sandstone_brick", + "default:silver_sandstone_brick", + {cracky = 2}, + {"default_silver_sandstone_brick.png"}, + "Silver Sandstone Brick Stair", + "Silver Sandstone Brick Slab", + default.node_sound_stone_defaults() +) + +stairs.register_stair_and_slab( + "silver_sandstone_block", + "default:silver_sandstone_block", + {cracky = 2}, + {"default_silver_sandstone_block.png"}, + "Silver Sandstone Block Stair", + "Silver Sandstone Block Slab", + default.node_sound_stone_defaults() +) + stairs.register_stair_and_slab( "obsidian", "default:obsidian", @@ -533,3 +587,27 @@ stairs.register_stair_and_slab( "Gold Block Slab", default.node_sound_metal_defaults() ) + +stairs.register_stair_and_slab( + "ice", + "default:ice", + {cracky = 3, puts_out_fire = 1, cools_lava = 1}, + {"default_ice.png"}, + "Ice Stair", + "Ice Slab", + default.node_sound_glass_defaults() +) + +stairs.register_stair_and_slab( + "snowblock", + "default:snowblock", + {crumbly = 3, puts_out_fire = 1, cools_lava = 1, snowy = 1}, + {"default_snow.png"}, + "Snow Block Stair", + "Snow Block Slab", + default.node_sound_dirt_defaults({ + footstep = {name = "default_snow_footstep", gain = 0.15}, + dug = {name = "default_snow_footstep", gain = 0.2}, + dig = {name = "default_snow_footstep", gain = 0.2} + }) +) diff --git a/mods/stairs/models/stairs_stair.obj b/mods/stairs/models/stairs_stair.obj index 45882c6e..198edf6e 100644 --- a/mods/stairs/models/stairs_stair.obj +++ b/mods/stairs/models/stairs_stair.obj @@ -55,7 +55,8 @@ usemtl None s off f 13/11/3 14/12/3 15/13/3 f 15/13/3 18/14/3 17/15/3 -f 14/12/3 16/16/3 18/14/3 +f 14/12/3 16/16/3 15/13/3 +f 16/16/3 18/14/3 15/13/3 o stairs_left v 0.500000 0.000000 0.000000 v 0.500000 -0.500000 -0.500000 @@ -75,7 +76,8 @@ usemtl None s off f 19/17/4 20/18/4 21/19/4 f 19/17/4 23/20/4 24/21/4 -f 20/18/4 24/21/4 22/22/4 +f 20/18/4 19/17/4 22/22/4 +f 19/17/4 24/21/4 22/22/4 o stairs_back v -0.500000 -0.500000 0.500000 v 0.500000 -0.500000 0.500000 diff --git a/mods/tnt/README.txt b/mods/tnt/README.txt index c1ca88d5..4e74841c 100644 --- a/mods/tnt/README.txt +++ b/mods/tnt/README.txt @@ -31,7 +31,10 @@ in mining. How to use the mod: Craft gunpowder by placing coal and gravel in the crafting area. The gunpowder can be used to craft TNT or as fuse for TNT. -To craft TNT surround gunpowder with 4 wood in a + shape. +To craft TNT place items like this: +-- wood - gunpowder -- wood - +gunpowder gunpowder gunpowder +-- wood - gunpowder -- wood - There are different ways to blow up TNT: 1. Hit it with a torch. diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua index f9bc307c..f54b2f1a 100644 --- a/mods/tnt/init.lua +++ b/mods/tnt/init.lua @@ -1,7 +1,7 @@ tnt = {} -- Default to enabled when in singleplayer -local enable_tnt = minetest.setting_getbool("enable_tnt") +local enable_tnt = minetest.settings:get_bool("enable_tnt") if enable_tnt == nil then enable_tnt = minetest.is_singleplayer() end @@ -12,7 +12,7 @@ local loss_prob = {} loss_prob["default:cobble"] = 3 loss_prob["default:dirt"] = 4 -local tnt_radius = tonumber(minetest.setting_get("tnt_radius") or 3) +local tnt_radius = tonumber(minetest.settings:get("tnt_radius") or 3) -- Fill a list with data for content IDs, after all nodes are registered local cid_data = {} @@ -83,7 +83,10 @@ local function add_drop(drops, item) end end -local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_protection, ignore_on_blast) +local basic_flame_on_construct -- cached value +local function destroy(drops, npos, cid, c_air, c_fire, + on_blast_queue, on_construct_queue, + ignore_protection, ignore_on_blast) if not ignore_protection and minetest.is_protected(npos, "") then return cid end @@ -93,9 +96,16 @@ local function destroy(drops, npos, cid, c_air, c_fire, on_blast_queue, ignore_p if not def then return c_air elseif not ignore_on_blast and def.on_blast then - on_blast_queue[#on_blast_queue + 1] = {pos = vector.new(npos), on_blast = def.on_blast} + on_blast_queue[#on_blast_queue + 1] = { + pos = vector.new(npos), + on_blast = def.on_blast + } return cid elseif def.flammable then + on_construct_queue[#on_construct_queue + 1] = { + fn = basic_flame_on_construct, + pos = vector.new(npos) + } return c_fire else local node_drops = minetest.get_node_drops(def.name, "") @@ -250,13 +260,15 @@ end function tnt.burn(pos, nodename) local name = nodename or minetest.get_node(pos).name - local group = minetest.get_item_group(name, "tnt") - if group > 0 then + local def = minetest.registered_nodes[name] + if not def then + return + elseif def.on_ignite then + def.on_ignite(pos) + elseif minetest.get_item_group(name, "tnt") > 0 then minetest.sound_play("tnt_ignite", {pos = pos}) minetest.set_node(pos, {name = name .. "_burning"}) minetest.get_node_timer(pos):start(1) - elseif name == "tnt:gunpowder" then - minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) end end @@ -306,6 +318,8 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) local drops = {} local on_blast_queue = {} + local on_construct_queue = {} + basic_flame_on_construct = minetest.registered_nodes["fire:basic_flame"].on_construct local c_fire = minetest.get_content_id("fire:basic_flame") for z = -radius, radius do @@ -318,8 +332,8 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) local p = {x = pos.x + x, y = pos.y + y, z = pos.z + z} if cid ~= c_air then data[vi] = destroy(drops, p, cid, c_air, c_fire, - on_blast_queue, ignore_protection, - ignore_on_blast) + on_blast_queue, on_construct_queue, + ignore_protection, ignore_on_blast) end end vi = vi + 1 @@ -357,6 +371,10 @@ local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast) end end + for _, queued_data in pairs(on_construct_queue) do + queued_data.fn(queued_data.pos) + end + return drops, radius end @@ -372,6 +390,8 @@ function tnt.boom(pos, def) eject_drops(drops, pos, radius) end add_effects(pos, radius, drops) + minetest.log("action", "A TNT explosion occurred at " .. minetest.pos_to_string(pos) .. + " with radius " .. radius) end minetest.register_node("tnt:boom", { @@ -397,7 +417,12 @@ minetest.register_node("tnt:gunpowder", { is_ground_content = false, sunlight_propagates = true, walkable = false, - tiles = {"tnt_gunpowder_straight.png", "tnt_gunpowder_curved.png", "tnt_gunpowder_t_junction.png", "tnt_gunpowder_crossing.png"}, + tiles = { + "tnt_gunpowder_straight.png", + "tnt_gunpowder_curved.png", + "tnt_gunpowder_t_junction.png", + "tnt_gunpowder_crossing.png" + }, inventory_image = "tnt_gunpowder_inventory.png", wield_image = "tnt_gunpowder_inventory.png", selection_box = { @@ -411,6 +436,9 @@ minetest.register_node("tnt:gunpowder", { on_punch = function(pos, node, puncher) if puncher:get_wielded_item():get_name() == "default:torch" then minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) + minetest.log("action", puncher:get_player_name() .. + " ignites tnt:gunpowder at " .. + minetest.pos_to_string(pos)) end end, on_blast = function(pos, intensity) @@ -471,7 +499,11 @@ minetest.register_node("tnt:gunpowder_burning", { fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, }, drop = "", - groups = {dig_immediate = 2, attached_node = 1, connect_to_raillike = minetest.raillike_group("gunpowder")}, + groups = { + dig_immediate = 2, + attached_node = 1, + connect_to_raillike = minetest.raillike_group("gunpowder") + }, sounds = default.node_sound_leaves_defaults(), on_timer = function(pos, elapsed) for dx = -1, 1 do @@ -498,7 +530,7 @@ minetest.register_node("tnt:gunpowder_burning", { }) minetest.register_craft({ - output = "tnt:gunpowder", + output = "tnt:gunpowder 5", type = "shapeless", recipe = {"default:coal_lump", "default:gravel"} }) @@ -507,9 +539,9 @@ if enable_tnt then minetest.register_craft({ output = "tnt:tnt", recipe = { - {"", "group:wood", ""}, - {"group:wood", "tnt:gunpowder", "group:wood"}, - {"", "group:wood", ""} + {"group:wood", "tnt:gunpowder", "group:wood"}, + {"tnt:gunpowder", "tnt:gunpowder", "tnt:gunpowder"}, + {"group:wood", "tnt:gunpowder", "group:wood"} } }) @@ -550,6 +582,9 @@ function tnt.register_tnt(def) on_punch = function(pos, node, puncher) if puncher:get_wielded_item():get_name() == "default:torch" then minetest.set_node(pos, {name = name .. "_burning"}) + minetest.log("action", puncher:get_player_name() .. + " ignites " .. node.name .. " at " .. + minetest.pos_to_string(pos)) end end, on_blast = function(pos, intensity) diff --git a/settingtypes.txt b/settingtypes.txt index eeea0bfc..855235c2 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -16,6 +16,9 @@ enable_fire (Fire) bool true # Enable flame sound. flame_sound (Flame sound) bool true +# Enable lavacooling. +enable_lavacooling (Lavacooling) bool true + # If enabled, steel tools, torches and cobblestone will be given to new # players. give_initial_stuff (Give initial items) bool false