commit b4ccf78d9c1965afa73b9f85aceb13f3a97deecd Author: James Stevenson Date: Sat Dec 15 11:28:11 2018 -0500 Glitchtest diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef02689 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +## Files related to minetest development cycle +/*.patch +# GNU Patch reject file +*.rej + +## Editors and Development environments +*~ +*.swp +*.bak* +*.orig +# Vim +*.vim +# Kate +.*.kate-swp +.swp.* +# Eclipse (LDT) +.project +.settings/ +.buildpath +.metadata +# Idea IDE +.idea/* diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..c3df64b --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,22 @@ +unused_args = false +allow_defined_top = true + +read_globals = { + "DIR_DELIM", + "minetest", "core", + "dump", + "vector", + "VoxelManip", "VoxelArea", + "PseudoRandom", "PcgRandom", + "ItemStack", + "Settings", + "unpack", + -- Silence errors about custom table methods. + table = { fields = { "copy", "indexof" } } +} + +-- Overwrites minetest.handle_node_drops +files["mods/creative/init.lua"].globals = { "minetest" } + +-- Don't report on legacy definitions of globals. +files["mods/default/legacy.lua"].global = false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5253938 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: generic +sudo: false +addons: + apt: + packages: + - luarocks +before_install: + - luarocks install --local luacheck +script: +- $HOME/.luarocks/bin/luacheck --no-color ./mods +notifications: + email: false diff --git a/3d_armor.LICENSE b/3d_armor.LICENSE new file mode 100644 index 0000000..18df885 --- /dev/null +++ b/3d_armor.LICENSE @@ -0,0 +1,9 @@ +3D Armor - Visible Player Armor +=============================== + +License Source Code: Copyright (C) 2013-2017 Stuart Jones - LGPL v2.1 + +Armor Textures: Copyright (C) 2017 davidthecreator - CC-BY-SA 3.0 + +Special credit to Jordach and MirceaKitsune for providing the default 3d character model. + diff --git a/3d_armor.README b/3d_armor.README new file mode 100644 index 0000000..cb16ec4 --- /dev/null +++ b/3d_armor.README @@ -0,0 +1,86 @@ +Modpack - 3d Armor [0.4.9] +========================== + +### Table of Contents + + + + +- [[mod] Visible Player Armor [3d_armor]](#mod-visible-player-armor-3d_armor) +- [[mod] Visible Wielded Items [wieldview]](#mod-visible-wielded-items-wieldview) +- [[mod] Shields [shields]](#mod-shields-shields) +- [[mod] Technic Armor [technic_armor]](#mod-technic-armor-technic_armor) +- [[mod] Hazmat Suit [hazmat_suit]](#mod-hazmat-suit-hazmat_suit) +- [[mod] 3d Armor Stand [3d_armor_stand]](#mod-3d-armor-stand-3d_armor_stand) + + + + +[mod] Visible Player Armor [3d_armor] +------------------------------------- + +Minetest Version: 0.4.16 + +Game: minetest_game and many derivatives + +Depends: default + +Adds craftable armor that is visible to other players. Each armor item worn contributes to +a player's armor group level making them less vulnerable to attack. + +Armor takes damage when a player is hurt, however, many armor items offer a 'stackable' +percentage chance of restoring the lost health points. Overall armor level is boosted by 10% +when wearing a full matching set (helmet, chestplate, leggings and boots of the same material) + +Fire protection has been added by TenPlus1 and in use when ethereal mod is found and crystal +armor has been enabled. each piece of armor offers 1 fire protection, level 1 protects +against torches, level 2 against crystal spikes, 3 for fire and 5 protects when in lava. + +Compatible with sfinv, inventory plus or unified inventory by enabling the appropriate +inventory module, [3d_armor_sfinv], [3d_armor_ip] and [3d_armor_ui] respectively. +Also compatible with [smart_inventory] without the need for additional modules. + +built in support player skins [skins] by Zeg9 and Player Textures [player_textures] by PilzAdam +and [simple_skins] by TenPlus1. + +Armor can be configured by adding a file called armor.conf in 3d_armor mod or world directory. +see armor.conf.example for all available options. + +[mod] Visible Wielded Items [wieldview] +--------------------------------------- + +Depends: 3d_armor + +Makes hand wielded items visible to other players. + +[mod] Shields [shields] +----------------------- + +Depends: 3d_armor + +Originally a part of 3d_armor, shields have been re-included as an optional extra. +If you do not want shields then simply remove the shields folder from the modpack. + +[mod] Technic Armor [technic_armor] +----------------------------------- + +Depends: 3d_armor, technic_worldgen + +Adds tin, silver and technic materials to 3d_armor. +Requires technic (technic_worldgen at least) mod. + +[mod] Hazmat Suit [hazmat_suit] +------------------------------- + +Depends: 3d_armor, technic + +Adds hazmat suit to 3d_armor. It protects rather well from fire (if enabled in configuration) and radiation*, and it has built-in oxygen supply. + +Requires technic mod. + +[mod] 3d Armor Stand [3d_armor_stand] +------------------------------------- + +Depends: 3d_armor + +Adds a chest-like armor stand for armor storage and display. diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..4bcefb9 --- /dev/null +++ b/BUGS @@ -0,0 +1,31 @@ +I fixed multiskin erroring on "default:dirt" texture. Now, it appears that when + joining the game as a node class, that when wielding a walkie after + changing back to miner results in the compass being shown behind the hearts! + [This should be okay, now. I just reorganized the order of hud flags + being set, seemed to work.] + +Sometimes switching to/from node class results in bugs. Like getting an item in your + hand from prior class. Or the hotbar on the hud showing visual glitches + (vertical lines). There's also the matter of multiskin attempting to set + player's skin to "default:dirt" and the like. + +Explosions seem to erase backpacks, other stuff. I did function() end on on_blast + for backpack, hopefully that helps. Still need to explode the contents. + +I was underground battling with Oerkki and NPCs, when I saw the minimap come on when I hit + the button. But, I didn't have a walkie! What? [Got it, forgot to turn it off + if wielded ~= walkie... -jas] + +Sometimes the player's HP (built-in statbar, not override (breath is hidden/off)) does not + display on the HUD. The reason, I suspect, is because I had a level 99 miner + and 1/99 HP shows as zero (out of twenty) on the HUD. I wonder if I can override + it easily, I don't want to redo the HP statbar, but I might eventually. [Update: + Armor suffers the same issue, if a very low value, shows as `0' on statbar!] + +When the player's `wielditem' (mod), in third person, item is constantly set, models resets. + Example: Holding a walkie talkie, which is always setting(?). Or updating something, + causing the model to reset (not fully animate, go back to frame 0 repeatedly)... + +The last item on the list of teleports in the bed formspec, if deleted, doesn't + update the index. So what happens is that once you delete the last + item, it won't work again until you select a new item. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..16c4ab4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,682 @@ ++----------------------------------------------------------------------+ +| Glitchtest is copyright (c) 2018 James Stevenson | +| | +| Code: GPL version 3 | +| Media: CC BY-SA 4 ++----------------------------------------------------------------------+ + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README b/README new file mode 100644 index 0000000..ba48c41 --- /dev/null +++ b/README @@ -0,0 +1 @@ +Glitchtest game diff --git a/TODO b/TODO new file mode 100644 index 0000000..dd53880 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +Make backpacks explode contents. +Learn Blender diff --git a/game.conf b/game.conf new file mode 100644 index 0000000..6eb7063 --- /dev/null +++ b/game.conf @@ -0,0 +1 @@ +name = Glitchtest diff --git a/game_api.txt b/game_api.txt new file mode 100644 index 0000000..47df8e7 --- /dev/null +++ b/game_api.txt @@ -0,0 +1,1017 @@ +Minetest Game API +================= +GitHub Repo: https://github.com/minetest/minetest_game + + +Introduction +------------ + +The Minetest Game game offers multiple new possibilities in addition to the Minetest engine's built-in API, +allowing you to add new plants to farming mod, buckets for new liquids, new stairs and custom panes. +For information on the Minetest API, visit https://github.com/minetest/minetest/blob/master/doc/lua_api.txt +Please note: + + * [XYZ] refers to a section the Minetest API + * [#ABC] refers to a section in this document + * [pos] refers to a position table `{x = -5, y = 0, z = 200}` + + +Bucket API +---------- + +The bucket API allows registering new types of buckets for non-default liquids. + + bucket.register_liquid( + "default:lava_source", -- name of the source node + "default:lava_flowing", -- name of the flowing node + "bucket:bucket_lava", -- name of the new bucket item (or nil if liquid is not takeable) + "bucket_lava.png", -- texture of the new bucket item (ignored if itemname == nil) + "Lava Bucket", -- text description of the bucket item + {lava_bucket = 1}, -- groups of the bucket item, OPTIONAL + false -- force-renew, OPTIONAL. Force the liquid source to renew if it has + -- a source neighbour, even if defined as 'liquid_renewable = false'. + -- Needed to avoid creating holes in sloping rivers. + ) + +The filled bucket item is returned to the player that uses an empty bucket pointing to the given liquid source. +When punching with an empty bucket pointing to an entity or a non-liquid node, the on_punch of the entity or node will be triggered. + + +Beds API +-------- + + beds.register_bed( + "beds:bed", -- Bed name + def -- See [#Bed definition] + ) + + * `beds.can_dig(bed_pos)` Returns a boolean whether the bed at `bed_pos` may be dug + * `beds.read_spawns() ` Returns a table containing players respawn positions + * `beds.kick_players()` Forces all players to leave bed + * `beds.skip_night()` Sets world time to morning and saves respawn position of all players currently sleeping + +### Bed definition + + { + description = "Simple Bed", + inventory_image = "beds_bed.png", + wield_image = "beds_bed.png", + tiles = { + bottom = {'Tile definition'}, -- the tiles of the bottom part of the bed. + top = {Tile definition} -- the tiles of the bottom part of the bed. + }, + nodebox = { + bottom = 'regular nodebox', -- bottom part of bed (see [Node boxes]) + top = 'regular nodebox', -- top part of bed (see [Node boxes]) + }, + selectionbox = 'regular nodebox', -- for both nodeboxes (see [Node boxes]) + recipe = { -- Craft recipe + {"group:wool", "group:wool", "group:wool"}, + {"group:wood", "group:wood", "group:wood"} + } + } + + +Bones API +--------- + +An ordered list of listnames (default: "main", "craft") of the player inventory, +that will be placed into bones or dropped on player death can be looked up or changed +in `bones.player_inventory_lists`. + +e.g. `table.insert(bones.player_inventory_lists, "backpack")` + + +Creative API +------------ + +Use `creative.register_tab(name, title, items)` to add a tab with filtered items. +For example, + + creative.register_tab("tools", "Tools", minetest.registered_tools) + +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. + + +Chests API +---------- + +The chests API allows the creation of chests, which have their own inventories for holding items. + +`default.chest.get_chest_formspec(pos)` + + * Returns a formspec for a specific chest. + * `pos` Location of the chest node, e.g `{x = 1, y = 1, z = 1}` + +`default.chest.chest_lid_obstructed(pos)` + + * Returns a boolean depending on whether or not a chest has its top obstructed by a solid node. + * `pos` Location of the chest node, e.g `{x = 1, y = 1, z = 1}` + +`default.chest.chest_lid_close(pn)` + + * Closes the chest that a player is currently looking in. + * `pn` The name of the player whose chest is going to be closed + +`default.chest.open_chests` + + * A table indexed by player name to keep track of who opened what chest. + * Key: The name of the player. + * Value: A table containing information about the chest the player is looking at. + e.g `{ pos = {1, 1, 1}, sound = null, swap = "chest" }` + +`default.chest.register_chest(name, def)` + + * Registers new chest + * `name` Name for chest + * `def` See [#Chest Definition] + +### Chest Definition + + 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" + }, -- Textures which are applied to the chest model. + 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 = false, -- If true, only placer can modify chest. + + +Doors API +--------- + +The doors mod allows modders to register custom doors and trapdoors. + +`doors.register_door(name, def)` + + * Registers new door + * `name` Name for door + * `def` See [#Door definition] + +`doors.register_trapdoor(name, def)` + + * Registers new trapdoor + * `name` Name for trapdoor + * `def` See [#Trapdoor definition] + +`doors.register_fencegate(name, def)` + + * Registers new fence gate + * `name` Name for fence gate + * `def` See [#Fence gate definition] + +`doors.get(pos)` + + * `pos` A position as a table, e.g `{x = 1, y = 1, z = 1}` + * Returns an ObjectRef to a door, or nil if the position does not contain a door + + ### Methods + + :open(player) -- Open the door object, returns if door was opened + :close(player) -- Close the door object, returns if door was closed + :toggle(player) -- Toggle the door state, returns if state was toggled + :state() -- returns the door state, true = open, false = closed + + the "player" parameter can be omitted in all methods. If passed then + the usual permission checks will be performed to make sure the player + has the permissions needed to open this door. If omitted then no + permission checks are performed. + +### Door definition + + description = "Door description", + inventory_image = "mod_door_inv.png", + groups = {choppy = 2}, + tiles = {"mod_door.png"}, -- UV map. + recipe = craftrecipe, + sounds = default.node_sound_wood_defaults(), -- optional + sound_open = sound play for open door, -- optional + sound_close = sound play for close door, -- optional + protected = false, -- If true, only placer can open the door (locked for others) + +### Trapdoor definition + + description = "Trapdoor description", + inventory_image = "mod_trapdoor_inv.png", + groups = {choppy = 2}, + tile_front = "doors_trapdoor.png", -- the texture for the front and back of the trapdoor + tile_side = "doors_trapdoor_side.png", -- the tiles of the four side parts of the trapdoor + sounds = default.node_sound_wood_defaults(), -- optional + sound_open = sound play for open door, -- optional + sound_close = sound play for close door, -- optional + protected = false, -- If true, only placer can open the door (locked for others) + +### Fence gate definition + + description = "Wooden Fence Gate", + texture = "default_wood.png", -- `backface_culling` will automatically be + -- set to `true` if not specified. + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults(), -- optional + + +Dungeon Loot API +---------------- + +The mod that places chests with loot in dungeons provides an API to register additional loot. + +`dungeon_loot.register(def)` + + * Registers one or more loot items + * `def` Can be a single [#Loot definition] or a list of them + +`dungeon_loot.registered_loot` + + * Table of all registered loot, not to be modified manually + +### Loot definition + + name = "item:name", + chance = 0.5, + -- ^ chance value from 0.0 to 1.0 that the item will appear in the chest when chosen + -- due to an extra step in the selection process, 0.5 does not(!) mean that + -- on average every second chest will have this item + count = {1, 4}, + -- ^ table with minimum and maximum amounts of this item + -- optional, defaults to always single item + y = {-32768, -512}, + -- ^ table with minimum and maximum heights this item can be found at + -- optional, defaults to no height restrictions + types = {"desert"}, + -- ^ table with types of dungeons this item can be found in + -- supported types: "normal" (the cobble/mossycobble one), "sandstone", "desert" + -- optional, defaults to no type restrictions + + +Fence API +--------- + +Allows creation of new fences with "fencelike" drawtype. + +`default.register_fence(name, item definition)` + + Registers a new fence. Custom fields texture and material are required, as + are name and description. The rest is optional. You can pass most normal + nodedef fields here except drawtype. The fence group will always be added + for this node. + +### fence definition + + name = "default:fence_wood", + description = "Wooden Fence", + texture = "default_wood.png", + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + + +Walls API +--------- + +The walls API allows easy addition of stone auto-connecting wall nodes. + +walls.register(name, desc, texture, mat, sounds) +^ name = "walls:stone_wall". Node name. +^ desc = "A Stone wall" +^ texture = "default_stone.png" +^ mat = "default:stone". Used to auto-generate crafting recipe. +^ sounds = sounds: see [#Default sounds] + + +Farming API +----------- + +The farming API allows you to easily register plants and hoes. + +`farming.register_hoe(name, hoe definition)` + * Register a new hoe, see [#hoe definition] + +`farming.register_plant(name, Plant definition)` + * Register a new growing plant, see [#Plant definition] + +`farming.registered_plants[name] = definition` + * Table of registered plants, indexed by plant name + +### Hoe Definition + + + { + description = "", -- Description for tooltip + inventory_image = "unknown_item.png", -- Image to be used as wield- and inventory image + max_uses = 30, -- Uses until destroyed + material = "", -- Material for recipes + recipe = { -- Craft recipe, if material isn't used + {"air", "air", "air"}, + {"", "group:stick"}, + {"", "group:stick"}, + } + } + +### Plant definition + + { + description = "", -- Description of seed item + inventory_image = "unknown_item.png", -- Image to be used as seed's wield- and inventory image + steps = 8, -- How many steps the plant has to grow, until it can be harvested + -- ^ Always provide a plant texture for each step, format: modname_plantname_i.png (i = stepnumber) + minlight = 13, -- Minimum light to grow + maxlight = default.LIGHT_MAX -- Maximum light to grow + } + + +Fire API +-------- + +New node def property: + +`on_burn(pos)` + + * Called when fire attempts to remove a burning node. + * `pos` Position of the burning node. + + `on_ignite(pos, igniter)` + + * Called when Flint and steel (or a mod defined ignitor) is used on a node. + Defining it may prevent the default action (spawning flames) from triggering. + * `pos` Position of the ignited node. + * `igniter` Player that used the tool, when available. + + +Give Initial Stuff API +---------------------- + +`give_initial_stuff.give(player)` + +^ Give initial stuff to "player" + +`give_initial_stuff.add(stack)` + +^ Add item to the initial stuff +^ Stack can be an ItemStack or a item name eg: "default:dirt 99" +^ Can be called after the game has loaded + +`give_initial_stuff.clear()` + +^ Removes all items from the initial stuff +^ Can be called after the game has loaded + +`give_initial_stuff.get_list()` + +^ returns list of item stacks + +`give_initial_stuff.set_list(list)` + +^ List of initial items with numeric indices. + +`give_initial_stuff.add_from_csv(str)` + +^ str is a comma separated list of initial stuff +^ Adds items to the list of items to be given + + +Players API +----------- + +The player API can register player models and update the player's appearence + +* `player_api.register_model(name, def)` + * Register a new model to be used by players + * name: model filename such as "character.x", "foo.b3d", etc. + * def: See [#Model definition] + * saved to player_api.registered_models + +* `player_api.registered_player_models[name]` + * Get a model's definition + * see [#Model definition] + +* `player_api.set_model(player, model_name)` + * Change a player's model + * `player`: PlayerRef + * `model_name`: model registered with player_api.register_model() + +* `player_api.set_animation(player, anim_name [, speed])` + * Applies an animation to a player + * anim_name: name of the animation. + * speed: frames per second. If nil, default from the model is used + +* `player_api.set_textures(player, textures)` + * Sets player textures + * `player`: PlayerRef + * `textures`: array of textures, If `textures` is nil the default + textures from the model def are used + +* `player_api.get_animation(player)` + * Returns a table containing fields `model`, `textures` and `animation`. + * Any of the fields of the returned table may be nil. + * player: PlayerRef + +### Model Definition + + { + animation_speed = 30, -- Default animation speed, in FPS. + textures = {"character.png", }, -- Default array of textures. + visual_size = {x = 1, y = 1}, -- Used to scale the model. + animations = { + -- = {x = , y = }, + foo = {x = 0, y = 19}, + bar = {x = 20, y = 39}, + -- ... + }, + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, -- In nodes from feet position + stepheight = 0.6, -- In nodes + eye_height = 1.47, -- In nodes above feet position + } + + +TNT API +------- + +`tnt.register_tnt(definition)` + +^ Register a new type of tnt. + + * `name` The name of the node. If no prefix is given `tnt` is used. + * `description` A description for your TNT. + * `radius` The radius within which the TNT can destroy nodes. The default is 3. + * `damage_radius` The radius within which the TNT can damage players and mobs. By default it is twice the `radius`. + * `sound` The sound played when explosion occurs. By default it is `tnt_explode`. + * `disable_drops` Disable drops. By default it is set to false. + * `ignore_protection` Don't check `minetest.is_protected` before removing a node. + * `ignore_on_blast` Don't call `on_blast` even if a node has one. + * `tiles` Textures for node + * `side` Side tiles. By default the name of the tnt with a suffix of `_side.png`. + * `top` Top tile. By default the name of the tnt with a suffix of `_top.png`. + * `bottom` Bottom tile. By default the name of the tnt with a suffix of `_bottom.png`. + * `burning` Top tile when lit. By default the name of the tnt with a suffix of `_top_burning_animated.png". + +`tnt.boom(position[, definition])` + +^ Create an explosion. + +* `position` The center of explosion. +* `definition` The TNT definion as passed to `tnt.register` with the following addition: + * `explode_center` false by default which removes TNT node on blast, when true will explode center node. + +`tnt.burn(position, [nodename])` + +^ 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': + +default.get_inventory_drops(pos, inventory, drops) + +^ Return drops from node inventory "inventory" in drops. + +* `pos` - the node position +* `inventory` - the name of the inventory (string) +* `drops` - an initialized list + +The function returns no values. The drops are returned in the `drops` +parameter, and drops is not reinitialized so you can call it several +times in a row to add more inventory items to it. + + +`on_blast` callbacks: + +Both nodedefs and entitydefs can provide an `on_blast()` callback + +`nodedef.on_blast(pos, intensity)` +^ Allow drop and node removal overriding +* `pos` - node position +* `intensity` - TNT explosion measure. larger or equal to 1.0 +^ Should return a list of drops (e.g. {"default:stone"}) +^ Should perform node removal itself. If callback exists in the nodedef +^ then the TNT code will not destroy this node. + +`entitydef.on_blast(luaobj, damage)` +^ Allow TNT effects on entities to be overridden +* `luaobj` - LuaEntityRef of the entity +* `damage` - suggested HP damage value +^ Should return a list of (bool do_damage, bool do_knockback, table drops) +* `do_damage` - if true then TNT mod wil damage the entity +* `do_knockback` - if true then TNT mod will knock the entity away +* `drops` - a list of drops, e.g. {"wool:red"} + + +Screwdriver API +--------------- + +The screwdriver API allows you to control a node's behaviour when a screwdriver is used on it. +To use it, add the `on_screwdriver` function to the node definition. + +`on_rotate(pos, node, user, mode, new_param2)` + + * `pos` Position of the node that the screwdriver is being used on + * `node` that node + * `user` The player who used the screwdriver + * `mode` screwdriver.ROTATE_FACE or screwdriver.ROTATE_AXIS + * `new_param2` the new value of param2 that would have been set if on_rotate wasn't there + * return value: false to disallow rotation, nil to keep default behaviour, true to allow + it but to indicate that changed have already been made (so the screwdriver will wear out) + * use `on_rotate = false` to always disallow rotation + * use `on_rotate = screwdriver.rotate_simple` to allow only face rotation + + +Sethome API +----------- + +The sethome API adds three global functions to allow mods to read a players home position, +set a players home position and teleport a player to home position. + +`sethome.get(name)` + + * `name` Player who's home position you wish to get + * return value: false if no player home coords exist, position table if true + +`sethome.set(name, pos)` + + * `name` Player who's home position you wish to set + * `pos` Position table containing coords of home position + * return value: false if unable to set and save new home position, otherwise true + +`sethome.go(name)` + + * `name` Player you wish to teleport to their home position + * return value: false if player cannot be sent home, otherwise true + + +Sfinv API +--------- + +It is recommended that you read this link for a good introduction to the +sfinv API by its author: https://rubenwardy.com/minetest_modding_book/en/chapters/sfinv.html + +### sfinv Methods + +**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.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 + +* pages - table of pages[pagename] = def +* pages_unordered - array table of pages in order of addition (used to build navigation tabs). +* contexts - contexts[playername] = player_context +* enabled - set to false to disable. Good for inventory rehaul mods like unified inventory + +### Context + +A table with these keys: + +* page - current page name +* nav - a list of page names +* nav_titles - a list of page titles +* nav_idx - current nav index (in nav and nav_titles) +* any thing you want to store + * sfinv will clear the stored data on log out / log in + +### sfinv.register_page + +sfinv.register_page(name, def) + +def is a table containing: + +* `title` - human readable page name (required) +* `get(self, player, context)` - returns a formspec string. See formspec variables. (required) +* `is_in_nav(self, player, context)` - return true to show in the navigation (the tab header, by default) +* `on_player_receive_fields(self, player, context, fields)` - on formspec submit. +* `on_enter(self, player, context)` - called when the player changes pages, usually using the tabs. +* `on_leave(self, player, context)` - when leaving this page to go to another, called before other's on_enter + +### get formspec + +Use sfinv.make_formspec to apply a layout: + + return sfinv.make_formspec(player, context, [[ + list[current_player;craft;1.75,0.5;3,3;] + list[current_player;craftpreview;5.75,1.5;1,1;] + image[4.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270] + listring[current_player;main] + listring[current_player;craft] + image[0,4.25;1,1;gui_hb_bg.png] + image[1,4.25;1,1;gui_hb_bg.png] + image[2,4.25;1,1;gui_hb_bg.png] + image[3,4.25;1,1;gui_hb_bg.png] + image[4,4.25;1,1;gui_hb_bg.png] + image[5,4.25;1,1;gui_hb_bg.png] + image[6,4.25;1,1;gui_hb_bg.png] + image[7,4.25;1,1;gui_hb_bg.png] + ]], true) + +See above (methods section) for more options. + +### Customising themes + +Simply override this function to change the navigation: + + function sfinv.get_nav_fs(player, context, nav, current_idx) + return "navformspec" + end + +And override this function to change the layout: + + function sfinv.make_formspec(player, context, content, show_inv, size) + local tmp = { + size or "size[8,8.6]", + theme_main, + sfinv.get_nav_fs(player, context, context.nav_titles, context.nav_idx), + content + } + if show_inv then + tmp[4] = theme_inv + end + return table.concat(tmp, "") + end + + +Stairs API +---------- + +The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those +delivered with Minetest Game, to keep them compatible with other mods. + +`stairs.register_stair(subname, recipeitem, groups, images, description, sounds, worldaligntex)` + + * Registers a stair + * `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil` + * `groups`: See [Known damage and digging time defining groups] + * `images`: See [Tile definition] + * `description`: Used for the description field in the stair's definition + * `sounds`: See [#Default sounds] + * `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition] + +`stairs.register_slab(subname, recipeitem, groups, images, description, sounds, worldaligntex)` + + * Registers a slab + * `subname`: Basically the material name (e.g. cobble) used for the slab name. Nodename pattern: "stairs:slab_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble" + * `groups`: See [Known damage and digging time defining groups] + * `images`: See [Tile definition] + * `description`: Used for the description field in the slab's definition + * `sounds`: See [#Default sounds] + * `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition] + +`stairs.register_stair_inner(subname, recipeitem, groups, images, description, sounds, worldaligntex)` + + * Registers an inner corner stair + * `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_inner_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil` + * `groups`: See [Known damage and digging time defining groups] + * `images`: See [Tile definition] + * `description`: Used for the description field in the stair's definition + * `sounds`: See [#Default sounds] + * `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition] + +`stairs.register_stair_outer(subname, recipeitem, groups, images, description, sounds, worldaligntex)` + + * Registers an outer corner stair + * `subname`: Basically the material name (e.g. cobble) used for the stair name. Nodename pattern: "stairs:stair_outer_subname" + * `recipeitem`: Item used in the craft recipe, e.g. "default:cobble", may be `nil` + * `groups`: See [Known damage and digging time defining groups] + * `images`: See [Tile definition] + * `description`: Used for the description field in the stair's definition + * `sounds`: See [#Default sounds] + * `worldaligntex`: A bool to set all textures world-aligned. Default false. See [Tile definition] + +`stairs.register_stair_and_slab(subname, recipeitem, groups, images, desc_stair, desc_slab, sounds, worldaligntex)` + + * A wrapper for stairs.register_stair, stairs.register_slab, stairs.register_stair_inner, stairs.register_stair_outer + * Uses almost the same arguments as stairs.register_stair + * `desc_stair`: Description for stair nodes. For corner stairs 'Inner' or 'Outer' will be prefixed + * `desc_slab`: Description for slab node + + +Xpanes API +---------- + +Creates panes that automatically connect to each other + +`xpanes.register_pane(subname, def)` + + * `subname`: used for nodename. Result: "xpanes:subname" and "xpanes:subname_{2..15}" + * `def`: See [#Pane definition] + +### Pane definition + + { + textures = {"texture for sides", (unused), "texture for top and bottom"}, -- More tiles aren't supported + groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups] + sounds = SoundSpec, -- See [#Default sounds] + recipe = {{"","","","","","","","",""}}, -- Recipe field only + use_texture_alpha = true, -- Optional boolean (default: `false`) for colored glass panes + } + + +Raillike definitions +-------------------- + +The following nodes use the group `connect_to_raillike` and will only connect to +raillike nodes within this group and the same group value. +Use `minetest.raillike_group()` to get the group value. + +| Node type | Raillike group name +|-----------------------|--------------------- +| default:rail | "rail" +| tnt:gunpowder | "gunpowder" +| tnt:gunpowder_burning | "gunpowder" + +Example: +If you want to add a new rail type and want it to connect with default:rail, +add `connect_to_raillike=minetest.raillike_group("rail")` into the `groups` table +of your node. + + +Default sounds +-------------- + +Sounds inside the default table can be used within the sounds field of node definitions. + + * `default.node_sound_defaults()` + * `default.node_sound_stone_defaults()` + * `default.node_sound_dirt_defaults()` + * `default.node_sound_sand_defaults()` + * `default.node_sound_wood_defaults()` + * `default.node_sound_leaves_defaults()` + * `default.node_sound_glass_defaults()` + * `default.node_sound_metal_defaults()` + + +Default constants +----------------- + +`default.LIGHT_MAX` The maximum light level (see [Node definition] light_source) + + +GUI and formspecs +----------------- + +`default.get_hotbar_bg(x, y)` + + * Get the hotbar background as string, containing the formspec elements + * x: Horizontal position in the formspec + * y: Vertical position in the formspec + +`default.gui_bg` + + * Deprecated, remove from mods. + +`default.gui_bg_img` + + * Deprecated, remove from mods. + +`default.gui_slots` + + * Deprecated, remove from mods. + +`default.gui_survival_form` + + * Entire formspec for the survival inventory + +`default.get_furnace_active_formspec(fuel_percent, item_percent)` + + * Get the active furnace formspec using the defined GUI elements + * fuel_percent: Percent of how much the fuel is used + * item_percent: Percent of how much the item is cooked + +`default.get_furnace_inactive_formspec()` + + * Get the inactive furnace formspec using the defined GUI elements + + +Leafdecay +--------- + +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. + +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. + +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. + + +Dyes +---- + +Minetest Game dyes are registered with: + + groups = {dye = 1, color_ = 1}, + +To make recipes that will work with dyes from many mods, define them using the +dye group and the color groups. + +Dye color groups: + + * `color_white` + * `color_grey` + * `color_dark_grey` + * `color_black` + * `color_red` + * `color_pink` + * `color_orange` + * `color_brown` + * `color_yellow` + * `color_green` + * `color_dark_green` + * `color_blue` + * `color_cyan` + * `color_violet` + * `color_magenta` + +Example of one shapeless recipe using the dye group and a color group: + + minetest.register_craft({ + type = "shapeless", + output = ":item_yellow", + recipe = {":item_no_color", "group:dye,color_yellow"}, + }) + + +Trees +----- + + * `default.grow_tree(pos, is_apple_tree)` + * Grows a mgv6 tree or apple tree at pos + + * `default.grow_jungle_tree(pos)` + * Grows a mgv6 jungletree at pos + + * `default.grow_pine_tree(pos)` + * Grows a mgv6 pinetree at pos + + * `default.grow_new_apple_tree(pos)` + * Grows a new design apple tree at pos + + * `default.grow_new_jungle_tree(pos)` + * Grows a new design jungle tree at pos + + * `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_bush(pos)` + * Grows a bush at pos + + * `default.grow_acacia_bush(pos)` + * Grows an acaia bush at pos + + * `default.grow_pine_bush(pos)` + * Grows a pine bush at pos + + * `default.grow_blueberry_bush(pos)` + * Grows a blueberry bush at pos + + +Carts +----- + + carts.register_rail( + "mycarts:myrail", -- Rail name + nodedef, -- standard nodedef + railparams -- rail parameter struct (optional) + ) + + railparams = { + on_step(obj, dtime), -- Event handler called when + -- cart is on rail + acceleration, -- integer acceleration factor (negative + -- values to brake) + } + + The event handler is called after all default calculations + are made, so the custom on_step handler can override things + like speed, acceleration, player attachment. The handler will + likely be called many times per second, so the function needs + to make sure that the event is handled properly. + + +Key API +------- + +The key API allows mods to add key functionality to nodes that have +ownership or specific permissions. Using the API will make it so +that a node owner can use skeleton keys on their nodes to create keys +for that node in that location, and give that key to other players, +allowing them some sort of access that they otherwise would not have +due to node protection. + +To make your new nodes work with the key API, you need to register +two callback functions in each nodedef: + + +`on_key_use(pos, player)` + * Is called when a player right-clicks (uses) a normal key on your + * node. + * `pos` - position of the node + * `player` - PlayerRef + * return value: none, ignored + +The `on_key_use` callback should validate that the player is wielding +a key item with the right key meta secret. If needed the code should +deny access to the node functionality. + +If formspecs are used, the formspec callbacks should duplicate these +checks in the metadata callback functions. + + +`on_skeleton_key_use(pos, player, newsecret)` + + * Is called when a player right-clicks (uses) a skeleton key on your + * node. + * `pos` - position of the node + * `player` - PlayerRef + * `newsecret` - a secret value(string) + * return values: + * `secret` - `nil` or the secret value that unlocks the door + * `name` - a string description of the node ("a locked chest") + * `owner` - name of the node owner + +The `on_skeleton_key_use` function should validate that the player has +the right permissions to make a new key for the item. The newsecret +value is useful if the node has no secret value. The function should +store this secret value somewhere so that in the future it may compare +key secrets and match them to allow access. If a node already has a +secret value, the function should return that secret value instead +of the newsecret value. The secret value stored for the node should +not be overwritten, as this would invalidate existing keys. + +Aside from the secret value, the function should retun a descriptive +name for the node and the owner name. The return values are all +encoded in the key that will be given to the player in replacement +for the wielded skeleton key. + +if `nil` is returned, it is assumed that the wielder did not have +permissions to create a key for this node, and no key is created. diff --git a/menu/header.png b/menu/header.png new file mode 100644 index 0000000..2c49030 Binary files /dev/null and b/menu/header.png differ diff --git a/menu/icon.png b/menu/icon.png new file mode 100644 index 0000000..f06997f Binary files /dev/null and b/menu/icon.png differ diff --git a/minetest.conf b/minetest.conf new file mode 100644 index 0000000..cefecf5 --- /dev/null +++ b/minetest.conf @@ -0,0 +1,43 @@ +#3d_armor +armor_material_wood = true +armor_material_cactus = true +armor_material_steel = true +armor_material_bronze = true +armor_material_diamond = true +armor_material_gold = true +#armor_init_delay = 1 +#armor_init_times = 1 +#armor_bones_delay = 1 +#armor_update_time = 1 +#armor_drop = true +#armor_destroy = false +#armor_level_multiplier = 1 +armor_heal_multiplier = 0 +#armor_water_protect = true +#armor_fire_protect = false +#armor_punch_damage = true +#armor_migrate_old_inventory = true + +#bones +share_bones_time = 300 +share_bones_time_early = 60 +bones_position_message = true + +#give_initial_stuff +give_initial_stuff = true +initial_stuff = walkie:talkie + +#tnt +enable_tnt = true + +#fire +enable_fire = true + +#sneak_jeak +sneak_jump.food_governor = 0.5 +sneak_jump.regen_rate = 1 +sneak_jump.drain_rate = 0.075 +sneak_jump.fill_rate = 0.5 + +#mobs +remove_far_mobs = false diff --git a/minetest.conf.example b/minetest.conf.example new file mode 100644 index 0000000..452251e --- /dev/null +++ b/minetest.conf.example @@ -0,0 +1,66 @@ +# This file contains settings of Minetest Game that can be changed in +# minetest.conf. +# By default, all the settings are commented and not functional. +# Uncomment settings by removing the preceding #. + +# Whether creative mode (fast digging of all blocks, unlimited resources) should +# be enabled. +#creative_mode = false + +# Sets the behaviour of the inventory items when a player dies. +# bones: Store items in a bone node but drop items if inside protected area. +# drop: Drop items on the ground. +# keep: Player keeps items. +#bones_mode = bones + +# The time in seconds after which the bones of a dead player can be looted by +# everyone. +# 0 to disable. +#share_bones_time = 1200 + +# How much earlier the bones of a dead player can be looted by +# everyone if the player dies in a protected area they don't own. +# 0 to disable. By default it is "share_bones_time" divide by four. +#share_bones_time_early = 300 + +# Inform player of condition and location of new bones. +#bones_position_message = false + +# Whether fire should be enabled. If disabled, 'basic_flame' nodes will +# disappear. +# 'permanent_flame' nodes will remain with either setting. +#enable_fire = true + +# 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 + +# Whether the TNT mod should be enabled. +#enable_tnt = + +# The radius of a TNT explosion. +#tnt_radius = 3 + +# Enable the stairs mod ABM that replaces the old 'upside down' +# stair and slab nodes in old maps with the new param2 versions. +#enable_stairs_replace_abm = false + +# Whether to allow respawning in beds. +# Default value is true. +#enable_bed_respawn = true + +# Whether players can skip night by sleeping. +# Default value is true. +#enable_bed_night_skip = true + +# Whether the engine's spawn search, which does not check for a suitable +# starting biome, is used. +# Default value is false. +#engine_spawn = false diff --git a/mods/3d_armor/LICENSE.txt b/mods/3d_armor/LICENSE.txt new file mode 100644 index 0000000..e1949c0 --- /dev/null +++ b/mods/3d_armor/LICENSE.txt @@ -0,0 +1,9 @@ +[mod] 3d Armor [3d_armor] +========================= + +License Source Code: (C) 2012-2017 Stuart Jones - LGPL v2.1 + +License Textures: Copyright (C) 2017 davidthecreator - CC-BY-SA 3.0 + +https://github.com/daviddoesminetest/3d-armors-new-textures + diff --git a/mods/3d_armor/README.txt b/mods/3d_armor/README.txt new file mode 100644 index 0000000..a0cb3b1 --- /dev/null +++ b/mods/3d_armor/README.txt @@ -0,0 +1,191 @@ +[mod] Visible Player Armor [3d_armor] +===================================== + +Depends: default + +Recommends: sfinv, unified_inventory or smart_inventory (use only one to avoid conflicts) + +Supports: player_monoids and armor_monoid + +Adds craftable armor that is visible to other players. Each armor item worn contributes to +a player's armor group level making them less vulnerable to weapons. + +Armor takes damage when a player is hurt but also offers a percentage chance of healing. +Overall level is boosted by 10% when wearing a full matching set. + +Fire protection added by TenPlus1 when using crystal armor if Ethereal mod active, level 1 +protects against torches, level 2 for crystal spike, level 3 for fire, level 5 for lava. + +Armor Configuration +------------------- + +Override the following default settings by adding them to your minetest.conf file. + +-- Set false to disable individual armor materials. +armor_material_wood = true +armor_material_cactus = true +armor_material_steel = true +armor_material_bronze = true +armor_material_diamond = true +armor_material_gold = true +armor_material_mithril = true +armor_material_crystal = true + +-- Increase this if you get initialization glitches when a player first joins. +armor_init_delay = 1 + +-- Number of initialization attempts. +-- Use in conjunction with armor_init_delay if initialization problems persist. +armor_init_times = 1 + +-- Increase this if armor is not getting into bones due to server lag. +armor_bones_delay = 1 + +-- How often player armor items are updated. +armor_update_time = 1 + +-- Drop armor when a player dies. +-- Uses bones mod if present, otherwise items are dropped around the player. +armor_drop = true + +-- Pulverise armor when a player dies, overrides armor_drop. +armor_destroy = false + +-- You can use this to increase or decrease overall armor effectiveness, +-- eg: level_multiplier = 0.5 will reduce armor level by half. +armor_level_multiplier = 1 + +-- You can use this to increase or decrease overall armor healing, +-- eg: armor_heal_multiplier = 0 will disable healing altogether. +armor_heal_multiplier = 1 + +-- Enable water protection (periodically restores breath when activated) +armor_water_protect = true + +-- Enable fire protection (defaults true if using ethereal mod) +armor_fire_protect = false + +-- Enable punch damage effects. +armor_punch_damage = true + +-- Enable migration of old armor inventories +armor_migrate_old_inventory = true + +API +--- + +Armor Registration: + +armor:register_armor(name, def) + +Wrapper function for `minetest.register_tool`, while registering armor as +a tool item is still supported, this may be deprecated in future so new code +should use this method. + +Additional fields supported by 3d_armor: + + texture = + preview = + armor_groups = + damage_groups =
+ reciprocate_damage = + on_equip = + on_unequip = + on_destroy = + on_damage = + on_punched = + +armor:register_armor_group(group, base) + +Example: + +armor:register_armor_group("radiation", 100) + +armor:register_armor("mod_name:speed_boots", { + description = "Speed Boots", + inventory_image = "mod_name_speed_boots_inv.png", + texture = "mod_name_speed_boots.png", + preview = "mod_name_speed_boots_preview.png", + groups = {armor_feet=1, armor_use=500, physics_speed=1.2, flammable=1}, + armor_groups = {fleshy=10, radiation=10}, + damage_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1}, + reciprocate_damage = true, + on_destroy = function(player, index, stack) + local pos = player:getpos() + if pos then + minetest.sound_play({ + name = "mod_name_break_sound", + pos = pos, + gain = 0.5, + }) + end + end, +}) + +See armor.lua, technic_armor and shields mods for more examples. + +Default groups: + +Elements: armor_head, armor_torso, armor_legs, armor_feet +Attributes: armor_heal, armor_fire, armor_water +Physics: physics_jump, physics_speed, physics_gravity +Durability: armor_use, flammable + +Notes: + +Elements may be modified by dependent mods, eg shields adds armor_shield. +Attributes and physics values are 'stackable', durability is determined +by the level of armor_use, total uses == approx (65535/armor_use), non-fleshy +damage groups need to be defined in the tool/weapon used against the player. + +Reciprocal tool damage will be done only by the first armor inventory item + with `reciprocate_damage = true` + +Armor Functions: + +armor:set_player_armor(player) + +Primarily an internal function but can be called externally to apply any +changes that might not otherwise get handled. + +armor:punch(player, hitter, time_from_last_punch, tool_capabilities) + +Used to apply damage to all equipped armor based on the damage groups of +each individual item.`hitter`, `time_from_last_punch` and `tool_capabilities` +are optional but should be valid if included. + +armor:damage(player, index, stack, use) + +Adds wear to a single armor itemstack, triggers `on_damage` callbacks and +updates the necessary inventories. Also handles item destruction callbacks +and so should NOT be called from `on_unequip` to avoid an infinite loop. + +Item Callbacks: + +on_equip = func(player, index, stack) +on_unequip = func(player, index, stack) +on_destroy = func(player, index, stack) +on_damage = func(player, index, stack) +on_punched = func(player, hitter, time_from_last_punch, tool_capabilities) + +Notes: + +`on_punched` is called every time a player is punched or takes damage, `hitter`, +`time_from_last_punch` and `tool_capabilities` can be `nil` and will be in the +case of fall damage, etc. When fire protection is enabled, hitter == "fire" +in the event of fire damage. Return `false` to override armor damage effects. +When armor is destroyed `stack` will contain a copy of the previous stack. + +Global Callbacks: + +armor:register_on_update(func(player)) +armor:register_on_equip(func(player, index, stack)) +armor:register_on_unequip(func(player, index, stack)) +armor:register_on_destroy(func(player, index, stack)) + +Global Callback Example: + +armor:register_on_update(function(player) + print(player:get_player_name().." armor updated!") +end) + diff --git a/mods/3d_armor/api.lua b/mods/3d_armor/api.lua new file mode 100644 index 0000000..4228b1a --- /dev/null +++ b/mods/3d_armor/api.lua @@ -0,0 +1,516 @@ +local use_multiskin = minetest.global_exists("multiskin") +local use_player_monoids = minetest.global_exists("player_monoids") +local use_armor_monoid = minetest.global_exists("armor_monoid") +local armor_def = setmetatable({}, { + __index = function() + return setmetatable({ + groups = setmetatable({}, { + __index = function() + return 0 + end}) + }, { + __index = function() + return 0 + end + }) + end, +}) +local armor_textures = setmetatable({}, { + __index = function() + return setmetatable({}, { + __index = function() + return "blank.png" + end + }) + end +}) + +armor = { + timer = 0, + elements = {"head", "torso", "legs", "feet"}, + physics = {"jump", "speed", "gravity"}, + attributes = {"heal", "fire", "water"}, + formspec = "image[2.5,0;2,4;armor_preview]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + default.get_hotbar_bg(0, 4.7).. + "list[current_player;main;0,4.7;8,1;]".. + "list[current_player;main;0,5.85;8,3;8]", + def = armor_def, + textures = armor_textures, + default_skin = "character.png", + materials = { + wood = "group:wood", + cactus = "default:cactus", + steel = "default:steel_ingot", + bronze = "default:bronze_ingot", + diamond = "default:diamond", + gold = "default:gold_ingot", + mithril = "moreores:mithril_ingot", + crystal = "ethereal:crystal_ingot", + }, + fire_nodes = { + {"default:lava_source", 5, 8}, + {"default:lava_flowing", 5, 8}, + {"fire:basic_flame", 3, 4}, + {"fire:permanent_flame", 3, 4}, + {"ethereal:crystal_spike", 2, 1}, + {"ethereal:fire_flower", 2, 1}, + {"default:torch", 1, 1}, + {"default:torch_ceiling", 1, 1}, + {"default:torch_wall", 1, 1}, + }, + registered_groups = {["fleshy"]=100}, + registered_callbacks = { + on_update = {}, + on_equip = {}, + on_unequip = {}, + on_damage = {}, + on_destroy = {}, + }, + migrate_old_inventory = true, + version = "0.4.9", +} + +armor.config = { + init_delay = 2, + init_times = 10, + bones_delay = 1, + update_time = 1, + drop = minetest.get_modpath("bones") ~= nil, + destroy = false, + level_multiplier = 1, + heal_multiplier = 1, + material_wood = true, + material_cactus = true, + material_steel = true, + material_bronze = true, + material_diamond = true, + material_gold = true, + material_mithril = true, + material_crystal = true, + water_protect = true, + fire_protect = minetest.get_modpath("ethereal") ~= nil, + punch_damage = true, +} + +-- Armor Registration + +armor.register_armor = function(self, name, def) + minetest.register_tool(name, def) +end + +armor.register_armor_group = function(self, group, base) + base = base or 100 + self.registered_groups[group] = base + if use_armor_monoid then + armor_monoid.register_armor_group(group, base) + end +end + +-- Armor callbacks + +armor.register_on_update = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_update, func) + end +end + +armor.register_on_equip = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_equip, func) + end +end + +armor.register_on_unequip = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_unequip, func) + end +end + +armor.register_on_damage = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_damage, func) + end +end + +armor.register_on_destroy = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_destroy, func) + end +end + +armor.run_callbacks = function(self, callback, player, index, stack) + if stack then + local def = stack:get_definition() or {} + if type(def[callback]) == "function" then + def[callback](player, index, stack) + end + end + local callbacks = self.registered_callbacks[callback] + if callbacks then + for _, func in pairs(callbacks) do + func(player, index, stack) + end + end +end + +armor.update_player_visuals = function(self, player) + local name = self:get_valid_player(player, "[update_player_visuals]") + if not name then + return + end + local textures = { + "blank.png", + "blank.png", + self.textures[name].armor, + self.textures[name].wielditem, + } + if use_multiskin then + multiskin.textures[name] = textures + multiskin.update_player_visuals(player) + else + textures[1] = armor.default_skin + default.player_set_textures(player, textures) + end + self:run_callbacks("on_update", player) +end + +armor.set_player_armor = function(self, player) + local name, armor_inv = self:get_valid_player(player, "[set_player_armor]") + if not name then + return + end + local state = 0 + local count = 0 + local material = {count=1} + local preview = "3d_armor_preview.png" + local texture = "blank.png" + local textures = {} + local physics = {} + local attributes = {} + local levels = {} + local groups = {} + local change = {} + if use_multiskin then + preview = multiskin.get_preview(player) or preview + end + for _, phys in pairs(self.physics) do + physics[phys] = 1 + end + for _, attr in pairs(self.attributes) do + attributes[attr] = 0 + end + for group, _ in pairs(self.registered_groups) do + change[group] = 1 + levels[group] = 0 + end + local list = armor_inv:get_list("armor") + if type(list) ~= "table" then + return + end + for i, stack in pairs(list) do + if stack:get_count() == 1 then + local def = stack:get_definition() + for _, element in pairs(self.elements) do + if def.groups["armor_"..element] then + if def.armor_groups then + for group, level in pairs(def.armor_groups) do + if levels[group] then + levels[group] = levels[group] + level + end + end + else + local level = def.groups["armor_"..element] + levels["fleshy"] = levels["fleshy"] + level + end + break + end + -- DEPRECATED, use armor_groups instead + if def.groups["armor_radiation"] and levels["radiation"] then + levels["radiation"] = def.groups["armor_radiation"] + end + end + local item = stack:get_name() + local tex = def.texture or item:gsub("%:", "_") + tex = tex:gsub(".png$", "") + local prev = def.preview or tex.."_preview" + prev = prev:gsub(".png$", "") + texture = texture.."^"..tex..".png" + preview = preview.."^"..prev..".png" + state = state + stack:get_wear() + count = count + 1 + for _, phys in pairs(self.physics) do + local value = def.groups["physics_"..phys] or 0 + physics[phys] = physics[phys] + value + end + for _, attr in pairs(self.attributes) do + local value = def.groups["armor_"..attr] or 0 + attributes[attr] = attributes[attr] + value + end + local mat = string.match(item, "%:.+_(.+)$") + if material.name then + if material.name == mat then + material.count = material.count + 1 + end + else + material.name = mat + end + end + end + for group, level in pairs(levels) do + if level > 0 then + level = level * armor.config.level_multiplier + if material.name and material.count == #self.elements then + level = level * 1.1 + end + end + local base = self.registered_groups[group] + self.def[name].groups[group] = level + if level > base then + level = base + end + groups[group] = base - level + change[group] = groups[group] / base + end + for _, attr in pairs(self.attributes) do + self.def[name][attr] = attributes[attr] + end + for _, phys in pairs(self.physics) do + self.def[name][phys] = physics[phys] + end + if use_armor_monoid then + armor_monoid.monoid:add_change(player, change, "3d_armor:armor") + else + player:set_armor_groups(groups) + end + if use_player_monoids then + player_monoids.speed:add_change(player, physics.speed, + "3d_armor:physics") + player_monoids.jump:add_change(player, physics.jump, + "3d_armor:physics") + player_monoids.gravity:add_change(player, physics.gravity, + "3d_armor:physics") + else + --player:set_physics_override(physics) + end + self.textures[name].armor = texture + self.textures[name].preview = preview + self.def[name].level = self.def[name].groups.fleshy or 0 + self.def[name].state = state + self.def[name].count = count + self:update_player_visuals(player) + player:get_meta():set_int("3d_armor_wear", (65535 * count - state) / (65535 / 2) * 2) + sneak_jump.hud_update(player) +end + +armor.punch = function(self, player, hitter, time_from_last_punch, tool_capabilities) + local name, armor_inv = self:get_valid_player(player, "[punch]") + if not name then + return + end + local state = 0 + local count = 0 + local recip = true + local default_groups = {cracky=3, snappy=3, choppy=3, crumbly=3, level=1} + local list = armor_inv:get_list("armor") + for i, stack in pairs(list) do + if stack:get_count() == 1 then + local name = stack:get_name() + local use = minetest.get_item_group(name, "armor_use") or 0 + local damage = use > 0 + local def = stack:get_definition() or {} + if type(def.on_punched) == "function" then + damage = def.on_punched(player, hitter, time_from_last_punch, + tool_capabilities) ~= false and damage == true + end + if damage == true and tool_capabilities then + local damage_groups = def.damage_groups or default_groups + local level = damage_groups.level or 0 + local groupcaps = tool_capabilities.groupcaps or {} + local uses = 0 + damage = false + for group, caps in pairs(groupcaps) do + local maxlevel = caps.maxlevel or 0 + local diff = maxlevel - level + if diff == 0 then + diff = 1 + end + if diff > 0 and caps.times then + local group_level = damage_groups[group] + if group_level then + local time = caps.times[group_level] + if time then + local dt = time_from_last_punch or 0 + if dt > time / diff then + if caps.uses then + uses = caps.uses * math.pow(3, diff) + end + damage = true + break + end + end + end + end + end + if damage == true and recip == true and hitter and + def.reciprocate_damage == true and uses > 0 then + local item = hitter:get_wielded_item() + if item and item:get_name() ~= "" then + item:add_wear(65535 / uses) + hitter:set_wielded_item(item) + end + -- reciprocate tool damage only once + recip = false + end + end + if damage == true and hitter == "fire" then + damage = minetest.get_item_group(name, "flammable") > 0 + end + if damage == true then + self:damage(player, i, stack, use) + end + state = state + stack:get_wear() + count = count + 1 + end + end + self.def[name].state = state + self.def[name].count = count + player:get_meta():set_int("3d_armor_wear", (65535 * count - state) / (65535 / 2) * 2) + sneak_jump.hud_update(player) +end + +armor.damage = function(self, player, index, stack, use) + local old_stack = ItemStack(stack) + stack:add_wear(use) + self:run_callbacks("on_damage", player, index, stack) + self:set_inventory_stack(player, index, stack) + if stack:get_count() == 0 then + self:run_callbacks("on_unequip", player, index, old_stack) + self:run_callbacks("on_destroy", player, index, old_stack) + self:set_player_armor(player) + end +end + +armor.get_armor_formspec = function(self, name, listring) + if armor.def[name].init_time == 0 then + return "label[0,0;Armor not initialized!]" + end + local formspec = armor.formspec.. + "list[detached:"..name.."_armor;armor;0,0.5;2,3;]" + if listring == true then + formspec = formspec.."listring[current_player;main]".. + "listring[detached:"..name.."_armor;armor]" + end + formspec = formspec:gsub("armor_preview", armor.textures[name].preview) + formspec = formspec:gsub("armor_level", armor.def[name].level) + for _, attr in pairs(self.attributes) do + formspec = formspec:gsub("armor_attr_"..attr, armor.def[name][attr]) + end + for group, _ in pairs(self.registered_groups) do + formspec = formspec:gsub("armor_group_"..group, + armor.def[name].groups[group]) + end + return formspec +end + +armor.serialize_inventory_list = function(self, list) + local list_table = {} + for _, stack in ipairs(list) do + table.insert(list_table, stack:to_string()) + end + return minetest.serialize(list_table) +end + +armor.deserialize_inventory_list = function(self, list_string) + local list_table = minetest.deserialize(list_string) + local list = {} + for _, stack in ipairs(list_table or {}) do + table.insert(list, ItemStack(stack)) + end + return list +end + +armor.load_armor_inventory = function(self, player) + local msg = "[load_armor_inventory]" + local name = player:get_player_name() + if not name then + minetest.log("warning", S("3d_armor: Player name is nil @1", msg)) + return + end + local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"}) + if not armor_inv then + minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg)) + return + end + local armor_list_string = player:get_attribute("3d_armor_inventory") + if armor_list_string then + armor_inv:set_list("armor", self:deserialize_inventory_list(armor_list_string)) + return true + end +end + +armor.save_armor_inventory = function(self, player) + local msg = "[save_armor_inventory]" + local name = player:get_player_name() + if not name then + minetest.log("warning", S("3d_armor: Player name is nil @1", msg)) + return + end + local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"}) + if not armor_inv then + minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg)) + return + end + player:set_attribute("3d_armor_inventory", self:serialize_inventory_list(armor_inv:get_list("armor"))) +end + +armor.update_inventory = function(self, player) + -- DEPRECATED: Legacy inventory support +end + +armor.set_inventory_stack = function(self, player, i, stack) + local msg = "[set_inventory_stack]" + local name = player:get_player_name() + if not name then + minetest.log("warning", "3d_armor: Player name is nil "..msg) + return + end + local armor_inv = minetest.get_inventory({type="detached", name=name.."_armor"}) + if not armor_inv then + minetest.log("warning", S("3d_armor: Detached armor inventory is nil @1", msg)) + return + end + armor_inv:set_stack("armor", i, stack) + self:save_armor_inventory(player) +end + +armor.get_valid_player = function(self, player, msg) + msg = msg or "" + if not player then + minetest.log("warning", "3d_armor: Player reference is nil "..msg) + return + end + local name = player:get_player_name() + if not name then + minetest.log("warning", "3d_armor: Player name is nil "..msg) + return + end + local inv = minetest.get_inventory({type="detached", name=name.."_armor"}) + if not inv then + minetest.log("warning", "3d_armor: Player inventory is nil "..msg) + return + end + return name, inv +end + +armor.drop_armor = function(pos, stack) + local node = minetest.get_node_or_nil(pos) + if node then + local obj = minetest.add_item(pos, stack) + if obj then + obj:setvelocity({x=math.random(-1, 1), y=5, z=math.random(-1, 1)}) + end + end +end diff --git a/mods/3d_armor/armor.conf.example b/mods/3d_armor/armor.conf.example new file mode 100644 index 0000000..9ce34b4 --- /dev/null +++ b/mods/3d_armor/armor.conf.example @@ -0,0 +1,65 @@ +-- DEPRECATED, will not be supported in future versions + +-- See README.txt for new configuration options. + +-- Armor Configuration (defaults) + +-- You can remove any unwanted armor materials from this table. +-- Note that existing armor that is removed will show up as an unknown item. +ARMOR_MATERIALS = { + wood = "group:wood", + cactus = "default:cactus", + steel = "default:steel_ingot", + bronze = "default:bronze_ingot", + diamond = "default:diamond", + gold = "default:gold_ingot", + mithril = "moreores:mithril_ingot", + crystal = "ethereal:crystal_ingot", +} + +-- Enable fire protection (defaults true if using ethereal mod) +ARMOR_FIRE_PROTECT = false + +-- Fire protection nodes, (name, protection level, damage) +ARMOR_FIRE_NODES = { + {"default:lava_source", 5, 4}, + {"default:lava_flowing", 5, 4}, + {"fire:basic_flame", 3, 4}, + {"fire:permanent_flame", 3, 4}, + {"ethereal:crystal_spike", 2, 1}, + {"ethereal:fire_flower", 2, 1}, + {"default:torch", 1, 1}, +} + +-- Increase this if you get initialization glitches when a player first joins. +ARMOR_INIT_DELAY = 1 + +-- Number of initialization attempts. +-- Use in conjunction with ARMOR_INIT_DELAY if initialization problems persist. +ARMOR_INIT_TIMES = 1 + +-- Increase this if armor is not getting into bones due to server lag. +ARMOR_BONES_DELAY = 1 + +-- How often player armor/wield items are updated. +ARMOR_UPDATE_TIME = 1 + +-- Drop armor when a player dies. +-- Uses bones mod if present, otherwise items are dropped around the player. +ARMOR_DROP = true + +-- Pulverise armor when a player dies, overrides ARMOR_DROP. +ARMOR_DESTROY = false + +-- You can use this to increase or decrease overall armor effectiveness, +-- eg: ARMOR_LEVEL_MULTIPLIER = 0.5 will reduce armor level by half. +ARMOR_LEVEL_MULTIPLIER = 1 + +-- You can use this to increase or decrease overall armor healing, +-- eg: ARMOR_HEAL_MULTIPLIER = 0 will disable healing altogether. +ARMOR_HEAL_MULTIPLIER = 1 + +-- You can use this to increase or decrease overall armor radiation protection, +-- eg: ARMOR_RADIATION_MULTIPLIER = 0 will completely disable radiation protection. +-- Note: patched technic mod is required +ARMOR_RADIATION_MULTIPLIER = 1 diff --git a/mods/3d_armor/armor.lua b/mods/3d_armor/armor.lua new file mode 100644 index 0000000..e80259b --- /dev/null +++ b/mods/3d_armor/armor.lua @@ -0,0 +1,399 @@ +local S = function(s) return s end +if minetest.global_exists("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + S = intllib.make_gettext_pair() + else + -- Old method using text files. + S = intllib.Getter() + end +end +--[[ +armor:register_armor("3d_armor:helmet_admin", { + description = S("Admin Helmet"), + inventory_image = "3d_armor_inv_helmet_admin.png", + armor_groups = {fleshy=100}, + groups = {armor_head=1, armor_heal=100, armor_use=0, armor_water=1, + not_in_creative_inventory=1}, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +armor:register_armor("3d_armor:chestplate_admin", { + description = S("Admin Chestplate"), + inventory_image = "3d_armor_inv_chestplate_admin.png", + armor_groups = {fleshy=100}, + groups = {armor_torso=1, armor_heal=100, armor_use=0, + not_in_creative_inventory=1}, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +armor:register_armor("3d_armor:leggings_admin", { + description = S("Admin Leggings"), + inventory_image = "3d_armor_inv_leggings_admin.png", + armor_groups = {fleshy=100}, + groups = {armor_legs=1, armor_heal=100, armor_use=0, + not_in_creative_inventory=1}, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +armor:register_armor("3d_armor:boots_admin", { + description = S("Admin Boots"), + inventory_image = "3d_armor_inv_boots_admin.png", + armor_groups = {fleshy=100}, + groups = {armor_feet=1, armor_heal=100, armor_use=0, + not_in_creative_inventory=1}, + on_drop = function(itemstack, dropper, pos) + return + end, +}) + +minetest.register_alias("adminboots", "3d_armor:boots_admin") +minetest.register_alias("adminhelmet", "3d_armor:helmet_admin") +minetest.register_alias("adminchestplate", "3d_armor:chestplate_admin") +minetest.register_alias("adminleggings", "3d_armor:leggings_admin") +--]] +local armor_on_use = function(itemstack, user, pointed_thing) + local name = user:get_player_name() + local inv = minetest.get_inventory({type = "detached", + name = name .. "_armor"}) + local list = inv:get_list("armor") + local index = 0 + for i = 1, #list do + if list[i]:get_name() == "" then + inv:set_stack("armor", i, itemstack) + index = i + break + end + end + if index == 0 then + return itemstack + end + armor:save_armor_inventory(user) + armor:run_callbacks("on_equip", user, index, itemstack) + armor:set_player_armor(user) + return "" +end +if armor.materials.wood then + armor:register_armor("3d_armor:helmet_wood", { + description = S("Wood Helmet"), + inventory_image = "3d_armor_inv_helmet_wood.png", + groups = {armor_head=1, armor_heal=0, armor_use=2000, flammable=1}, + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_wood", { + description = S("Wood Chestplate"), + inventory_image = "3d_armor_inv_chestplate_wood.png", + groups = {armor_torso=1, armor_heal=0, armor_use=2000, flammable=1}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_wood", { + description = S("Wood Leggings"), + inventory_image = "3d_armor_inv_leggings_wood.png", + groups = {armor_legs=1, armor_heal=0, armor_use=2000, flammable=1}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_wood", { + description = S("Wood Boots"), + inventory_image = "3d_armor_inv_boots_wood.png", + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}, + groups = {armor_feet=1, armor_heal=0, armor_use=2000, flammable=1}, + on_use = armor_on_use, + }) +end + +if armor.materials.cactus then + armor:register_armor("3d_armor:helmet_cactus", { + description = S("Cactus Helmet"), + inventory_image = "3d_armor_inv_helmet_cactus.png", + groups = {armor_head=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_cactus", { + description = S("Cactus Chestplate"), + inventory_image = "3d_armor_inv_chestplate_cactus.png", + groups = {armor_torso=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_cactus", { + description = S("Cactus Leggings"), + inventory_image = "3d_armor_inv_leggings_cactus.png", + groups = {armor_legs=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=1}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_cactus", { + description = S("Cactus Boots"), + inventory_image = "3d_armor_inv_boots_cactus.png", + groups = {armor_feet=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=1}, + on_use = armor_on_use, + }) +end + +if armor.materials.steel then + armor:register_armor("3d_armor:helmet_steel", { + description = S("Steel Helmet"), + inventory_image = "3d_armor_inv_helmet_steel.png", + groups = {armor_head=1, armor_heal=0, armor_use=800, + physics_speed=-0.01, physics_gravity=0.01}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_steel", { + description = S("Steel Chestplate"), + inventory_image = "3d_armor_inv_chestplate_steel.png", + groups = {armor_torso=1, armor_heal=0, armor_use=800, + physics_speed=-0.04, physics_gravity=0.04}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_steel", { + description = S("Steel Leggings"), + inventory_image = "3d_armor_inv_leggings_steel.png", + groups = {armor_legs=1, armor_heal=0, armor_use=800, + physics_speed=-0.03, physics_gravity=0.03}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_steel", { + description = S("Steel Boots"), + inventory_image = "3d_armor_inv_boots_steel.png", + groups = {armor_feet=1, armor_heal=0, armor_use=800, + physics_speed=-0.01, physics_gravity=0.01}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) +end + +if armor.materials.bronze then + armor:register_armor("3d_armor:helmet_bronze", { + description = S("Bronze Helmet"), + inventory_image = "3d_armor_inv_helmet_bronze.png", + groups = {armor_head=1, armor_heal=6, armor_use=400, + physics_speed=-0.01, physics_gravity=0.01}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_bronze", { + description = S("Bronze Chestplate"), + inventory_image = "3d_armor_inv_chestplate_bronze.png", + groups = {armor_torso=1, armor_heal=6, armor_use=400, + physics_speed=-0.04, physics_gravity=0.04}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_bronze", { + description = S("Bronze Leggings"), + inventory_image = "3d_armor_inv_leggings_bronze.png", + groups = {armor_legs=1, armor_heal=6, armor_use=400, + physics_speed=-0.03, physics_gravity=0.03}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_bronze", { + description = S("Bronze Boots"), + inventory_image = "3d_armor_inv_boots_bronze.png", + groups = {armor_feet=1, armor_heal=6, armor_use=400, + physics_speed=-0.01, physics_gravity=0.01}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=3, snappy=2, choppy=2, crumbly=1, level=2}, + on_use = armor_on_use, + }) +end + +if armor.materials.diamond then + armor:register_armor("3d_armor:helmet_diamond", { + description = S("Diamond Helmet"), + inventory_image = "3d_armor_inv_helmet_diamond.png", + groups = {armor_head=1, armor_heal=12, armor_use=200}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, choppy=1, level=3}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_diamond", { + description = S("Diamond Chestplate"), + inventory_image = "3d_armor_inv_chestplate_diamond.png", + groups = {armor_torso=1, armor_heal=12, armor_use=200}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, choppy=1, level=3}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_diamond", { + description = S("Diamond Leggings"), + inventory_image = "3d_armor_inv_leggings_diamond.png", + groups = {armor_legs=1, armor_heal=12, armor_use=200}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, choppy=1, level=3}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_diamond", { + description = S("Diamond Boots"), + inventory_image = "3d_armor_inv_boots_diamond.png", + groups = {armor_feet=1, armor_heal=12, armor_use=200}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, choppy=1, level=3}, + on_use = armor_on_use, + }) +end + +if armor.materials.gold then + armor:register_armor("3d_armor:helmet_gold", { + description = S("Gold Helmet"), + inventory_image = "3d_armor_inv_helmet_gold.png", + groups = {armor_head=1, armor_heal=6, armor_use=300, + physics_speed=-0.02, physics_gravity=0.02}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=1, snappy=2, choppy=2, crumbly=3, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:chestplate_gold", { + description = S("Gold Chestplate"), + inventory_image = "3d_armor_inv_chestplate_gold.png", + groups = {armor_torso=1, armor_heal=6, armor_use=300, + physics_speed=-0.05, physics_gravity=0.05}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=1, snappy=2, choppy=2, crumbly=3, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:leggings_gold", { + description = S("Gold Leggings"), + inventory_image = "3d_armor_inv_leggings_gold.png", + groups = {armor_legs=1, armor_heal=6, armor_use=300, + physics_speed=-0.04, physics_gravity=0.04}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=1, snappy=2, choppy=2, crumbly=3, level=2}, + on_use = armor_on_use, + }) + armor:register_armor("3d_armor:boots_gold", { + description = S("Gold Boots"), + inventory_image = "3d_armor_inv_boots_gold.png", + groups = {armor_feet=1, armor_heal=6, armor_use=300, + physics_speed=-0.02, physics_gravity=0.02}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=1, snappy=2, choppy=2, crumbly=3, level=2}, + on_use = armor_on_use, + }) +end + +if armor.materials.mithril then + armor:register_armor("3d_armor:helmet_mithril", { + description = S("Mithril Helmet"), + inventory_image = "3d_armor_inv_helmet_mithril.png", + groups = {armor_head=1, armor_heal=12, armor_use=100}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:chestplate_mithril", { + description = S("Mithril Chestplate"), + inventory_image = "3d_armor_inv_chestplate_mithril.png", + groups = {armor_torso=1, armor_heal=12, armor_use=100}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:leggings_mithril", { + description = S("Mithril Leggings"), + inventory_image = "3d_armor_inv_leggings_mithril.png", + groups = {armor_legs=1, armor_heal=12, armor_use=100}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:boots_mithril", { + description = S("Mithril Boots"), + inventory_image = "3d_armor_inv_boots_mithril.png", + groups = {armor_feet=1, armor_heal=12, armor_use=100}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) +end + +if armor.materials.crystal then + armor:register_armor("3d_armor:helmet_crystal", { + description = S("Crystal Helmet"), + inventory_image = "3d_armor_inv_helmet_crystal.png", + groups = {armor_head=1, armor_heal=12, armor_use=100, armor_fire=1}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:chestplate_crystal", { + description = S("Crystal Chestplate"), + inventory_image = "3d_armor_inv_chestplate_crystal.png", + groups = {armor_torso=1, armor_heal=12, armor_use=100, armor_fire=1}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:leggings_crystal", { + description = S("Crystal Leggings"), + inventory_image = "3d_armor_inv_leggings_crystal.png", + groups = {armor_legs=1, armor_heal=12, armor_use=100, armor_fire=1}, + armor_groups = {fleshy=20}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) + armor:register_armor("3d_armor:boots_crystal", { + description = S("Crystal Boots"), + inventory_image = "3d_armor_inv_boots_crystal.png", + groups = {armor_feet=1, armor_heal=12, armor_use=100, physics_speed=1, + physics_jump=0.5, armor_fire=1}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + }) +end + +for k, v in pairs(armor.materials) do + minetest.register_craft({ + output = "3d_armor:helmet_"..k, + recipe = { + {v, v, v}, + {v, "", v}, + {"", "", ""}, + }, + }) + minetest.register_craft({ + output = "3d_armor:chestplate_"..k, + recipe = { + {v, "", v}, + {v, v, v}, + {v, v, v}, + }, + }) + minetest.register_craft({ + output = "3d_armor:leggings_"..k, + recipe = { + {v, v, v}, + {v, "", v}, + {v, "", v}, + }, + }) + minetest.register_craft({ + output = "3d_armor:boots_"..k, + recipe = { + {v, "", v}, + {v, "", v}, + }, + }) +end diff --git a/mods/3d_armor/crafting_guide.txt b/mods/3d_armor/crafting_guide.txt new file mode 100644 index 0000000..abd1519 --- /dev/null +++ b/mods/3d_armor/crafting_guide.txt @@ -0,0 +1,79 @@ +3d_armor -- Crafting Guide +-------------------------- + +Helmets: + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | | X | ++---+---+---+ +| | | | ++---+---+---+ + +[3d_armor:helmet_wood] X = [default:wood] +[3d_armor:helmet_cactus] X = [default:cactus] +[3d_armor:helmet_steel] X = [default:steel_ingot] +[3d_armor:helmet_bronze] X = [default:bronze_ingot] +[3d_armor:helmet_diamond] X = [default:diamond] +[3d_armor:helmet_gold] X = [default:gold_ingot] +[3d_armor:helmet_mithril] X = [moreores:mithril_ingot] * +[3d_armor:helmet_crystal] X = [ethereal:crystal_ingot] ** + +Chestplates: + ++---+---+---+ +| X | | X | ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | X | X | ++---+---+---+ + +[3d_armor:chestplate_wood] X = [default:wood] +[3d_armor:chestplate_cactus] X = [default:cactus] +[3d_armor:chestplate_steel] X = [default:steel_ingot] +[3d_armor:chestplate_bronze] X = [default:bronze_ingot] +[3d_armor:chestplate_diamond] X = [default:diamond] +[3d_armor:chestplate_gold] X = [default:gold_ingot] +[3d_armor:chestplate_mithril] X = [moreores:mithril_ingot] * +[3d_armor:chestplate_crystal] X = [ethereal:crystal_ingot] ** + +Leggings: + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | | X | ++---+---+---+ +| X | | X | ++---+---+---+ + +[3d_armor:leggings_wood] X = [default:wood] +[3d_armor:leggings_cactus] X = [default:cactus] +[3d_armor:leggings_steel] X = [default:steel_ingot] +[3d_armor:leggings_bronze] X = [default:bronze_ingot] +[3d_armor:leggings_diamond] X = [default:diamond] +[3d_armor:leggings_gold] X = [default:gold_ingot] +[3d_armor:leggings_mithril] X = [moreores:mithril_ingot] * +[3d_armor:leggings_crystal] X = [ethereal:crystal_ingot] ** + +Boots: + ++---+---+---+ +| X | | X | ++---+---+---+ +| X | | X | ++---+---+---+ + +[3d_armor:boots_wood] X = [default:wood] +[3d_armor:boots_cactus] X = [default:cactus] +[3d_armor:boots_steel] X = [default:steel_ingot] +[3d_armor:boots_bronze] X = [default:bronze_ingot +[3d_armor:boots_diamond] X = [default:diamond] +[3d_armor:boots_gold] X = [default:gold_ingot] +[3d_armor:boots_mithril] X = [moreores:mithril_ingot] * +[3d_armor:boots_crystal] X = [ethereal:crystal_ingot] ** + + * Requires moreores mod by Calinou - https://forum.minetest.net/viewtopic.php?id=549 +** Requires ethereal mod by Chinchow & TenPlus1 - https://github.com/tenplus1/ethereal diff --git a/mods/3d_armor/depends.txt b/mods/3d_armor/depends.txt new file mode 100644 index 0000000..f19b97e --- /dev/null +++ b/mods/3d_armor/depends.txt @@ -0,0 +1,8 @@ +default +player_monoids? +armor_monoid? +fire? +ethereal? +bakedclay? +intllib? +multiskin? diff --git a/mods/3d_armor/description.txt b/mods/3d_armor/description.txt new file mode 100644 index 0000000..b0a9b0a --- /dev/null +++ b/mods/3d_armor/description.txt @@ -0,0 +1 @@ +Adds craftable armor that is visible to other players. diff --git a/mods/3d_armor/init.lua b/mods/3d_armor/init.lua new file mode 100644 index 0000000..93d678f --- /dev/null +++ b/mods/3d_armor/init.lua @@ -0,0 +1,383 @@ +local S = function(s) return s end +if minetest.global_exists("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + S = intllib.make_gettext_pair() + else + -- Old method using text files. + S = intllib.Getter() + end +end +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) +local worldpath = minetest.get_worldpath() +local last_punch_time = {} +local pending_players = {} +local timer = 0 + +dofile(modpath.."/api.lua") + +-- Legacy Config Support + +local input = io.open(modpath.."/armor.conf", "r") +if input then + dofile(modpath.."/armor.conf") + input:close() + input = nil +end +input = io.open(worldpath.."/armor.conf", "r") +if input then + dofile(worldpath.."/armor.conf") + input:close() + input = nil +end +for name, _ in pairs(armor.config) do + local global = "ARMOR_"..name:upper() + if minetest.global_exists(global) then + armor.config[name] = _G[global] + end +end +if minetest.global_exists("ARMOR_MATERIALS") then + armor.materials = table.copy(ARMOR_MATERIALS) +end +if minetest.global_exists("ARMOR_FIRE_NODES") then + armor.fire_nodes = table.copy(ARMOR_FIRE_NODES) +end + +-- Load Configuration + +for name, config in pairs(armor.config) do + local setting = minetest.settings:get("armor_"..name) + if type(config) == "number" then + setting = tonumber(setting) + elseif type(config) == "boolean" then + setting = minetest.settings:get_bool("armor_"..name) + end + if setting ~= nil then + armor.config[name] = setting + end +end +for material, _ in pairs(armor.materials) do + local key = "material_"..material + if armor.config[key] == false then + armor.materials[material] = nil + end +end + +-- Mod Compatibility +if minetest.get_modpath("multiskin") then + multiskin.model = "3d_armor_character.b3d" +end +if minetest.get_modpath("technic") then + armor.formspec = armor.formspec.. + "label[5,2.5;"..S("Radiation")..": armor_group_radiation]" + armor:register_armor_group("radiation") +end +if not minetest.get_modpath("moreores") then + armor.materials.mithril = nil +end +if not minetest.get_modpath("ethereal") then + armor.materials.crystal = nil +end + +dofile(modpath.."/armor.lua") + +-- Armor Initialization + +armor.formspec = armor.formspec.. + "label[5,1;"..S("Level")..": armor_level]".. + "label[5,1.5;"..S("Heal")..": armor_attr_heal]" +if armor.config.fire_protect then + armor.formspec = armor.formspec.."label[5,2;"..S("Fire")..": armor_fire]" +end +armor:register_on_destroy(function(player, index, stack) + local name = player:get_player_name() + local def = stack:get_definition() + if name and def and def.description then + minetest.chat_send_player(name, S("Your").." "..def.description.." ".. + S("got destroyed").."!") + end +end) + +local function init_player_armor(player) + local name = player:get_player_name() + local pos = player:getpos() + if not name or not pos then + return false + end + local armor_inv = minetest.create_detached_inventory(name.."_armor", { + on_put = function(inv, listname, index, stack, player) + armor:save_armor_inventory(player) + armor:run_callbacks("on_equip", player, index, stack) + armor:set_player_armor(player) + end, + on_take = function(inv, listname, index, stack, player) + armor:save_armor_inventory(player) + armor:run_callbacks("on_unequip", player, index, stack) + armor:set_player_armor(player) + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + armor:save_armor_inventory(player) + armor:set_player_armor(player) + end, + allow_put = function(inv, listname, index, stack, player) + local def = stack:get_definition() or {} + local allowed = 0 + for _, element in pairs(armor.elements) do + if def.groups["armor_"..element] then + allowed = 1 + for i = 1, 6 do + local item = inv:get_stack("armor", i):get_name() + if minetest.get_item_group(item, "armor_"..element) > 0 then + return 0 + end + end + end + end + return allowed + end, + allow_take = function(inv, listname, index, stack, player) + return stack:get_count() + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return count + end, + }, name) + armor_inv:set_size("armor", 6) + if not armor:load_armor_inventory(player) and armor.migrate_old_inventory then + local player_inv = player:get_inventory() + player_inv:set_size("armor", 6) + for i=1, 6 do + local stack = player_inv:get_stack("armor", i) + armor_inv:set_stack("armor", i, stack) + end + armor:save_armor_inventory(player) + player_inv:set_size("armor", 0) + end + for i=1, 6 do + local stack = armor_inv:get_stack("armor", i) + armor:run_callbacks("on_equip", player, i, stack) + end + armor.def[name] = { + init_time = minetest.get_gametime(), + level = 0, + state = 0, + count = 0, + groups = {}, + } + for _, phys in pairs(armor.physics) do + armor.def[name][phys] = 1 + end + for _, attr in pairs(armor.attributes) do + armor.def[name][attr] = 0 + end + for group, _ in pairs(armor.registered_groups) do + armor.def[name].groups[group] = 0 + end + armor.textures[name] = { + armor = "blank.png", + wielditem = "blank.png", + } + minetest.after(0, function(player) + armor:set_player_armor(player) + end, player) + return true +end + +-- Armor Player Model + +default.player_register_model("3d_armor_character.b3d", { + animation_speed = 30, + textures = { + armor.default_skin, + "blank.png", + "blank.png", + "blank.png", + }, + animations = { + stand = {x=0, y=79}, + lay = {x=162, y=166}, + walk = {x=168, y=187}, + mine = {x=189, y=198}, + walk_mine = {x=200, y=219}, + sit = {x=81, y=160}, + }, +}) + +minetest.register_on_joinplayer(function(player) + default.player_set_model(player, "3d_armor_character.b3d") + minetest.after(0, function(player) + if init_player_armor(player) == false then + pending_players[player] = 0 + end + end, player) +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + if name then + armor.def[name] = nil + armor.textures[name] = nil + end + pending_players[player] = nil +end) + +if armor.config.drop == true or armor.config.destroy == true then + minetest.register_on_dieplayer(function(player) + local name, armor_inv = armor:get_valid_player(player, "[on_dieplayer]") + if not name then + return + end + local drop = {} + for i=1, armor_inv:get_size("armor") do + local stack = armor_inv:get_stack("armor", i) + if stack:get_count() > 0 then + table.insert(drop, stack) + armor:set_inventory_stack(player, i, nil) + armor:run_callbacks("on_unequip", player, i, stack) + end + end + armor:set_player_armor(player) + local pos = player:getpos() + if pos and armor.config.destroy == false then + minetest.after(armor.config.bones_delay, function() + local meta = nil + local maxp = vector.add(pos, 8) + local minp = vector.subtract(pos, 8) + local bones = minetest.find_nodes_in_area(minp, maxp, {"bones:bones"}) + for _, p in pairs(bones) do + local m = minetest.get_meta(p) + if m:get_string("owner") == name then + meta = m + break + end + end + if meta then + local inv = meta:get_inventory() + for _,stack in ipairs(drop) do + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + else + armor.drop_armor(pos, stack) + end + end + else + for _,stack in ipairs(drop) do + armor.drop_armor(pos, stack) + end + end + end) + end + end) +end + +if armor.config.punch_damage == true then + minetest.register_on_punchplayer(function(player, hitter, + time_from_last_punch, tool_capabilities) + local name = player:get_player_name() + if name then + armor:punch(player, hitter, time_from_last_punch, tool_capabilities) + last_punch_time[name] = minetest.get_gametime() + end + end) +end + +minetest.register_on_player_hpchange(function(player, hp_change) + if player and hp_change < 0 then + local name = player:get_player_name() + if name then + local heal = armor.def[name].heal + heal = heal * armor.config.heal_multiplier + if heal >= math.random(100) then + hp_change = 0 + end + -- check if armor damage was handled by fire or on_punchplayer + local time = last_punch_time[name] or 0 + if time == 0 or time + 1 < minetest.get_gametime() then + armor:punch(player) + end + -- Punch, fire, but what about damage from fire? + end + end + return hp_change +end, true) + +minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer > armor.config.init_delay then + for player, count in pairs(pending_players) do + local remove = init_player_armor(player) == true + pending_players[player] = count + 1 + if remove == false and count > armor.config.init_times then + minetest.log("warning", "3d_armor: Failed to initialize player") + remove = true + end + if remove == true then + pending_players[player] = nil + end + end + timer = 0 + end +end) + +-- Fire Protection and water breating, added by TenPlus1 + +if armor.config.fire_protect == true then + -- override hot nodes so they do not hurt player anywhere but mod + for _, row in pairs(armor.fire_nodes) do + if minetest.registered_nodes[row[1]] then + minetest.override_item(row[1], {damage_per_second = 0}) + end + end +--else + --print ("[3d_armor] Fire Nodes disabled") +end + +if armor.config.water_protect == true or armor.config.fire_protect == true then + minetest.register_globalstep(function(dtime) + armor.timer = armor.timer + dtime + if armor.timer < armor.config.update_time then + return + end + for _,player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local pos = player:getpos() + local hp = player:get_hp() + if not name or not pos or not hp then + return + end + -- water breathing + if armor.config.water_protect == true then + if armor.def[name].water > 0 and + player:get_breath() < 10 then + player:set_breath(10) + end + end + -- fire protection + if armor.config.fire_protect == true then + local fire_damage = true + pos.y = pos.y + 1.4 -- head level + local node_head = minetest.get_node(pos).name + pos.y = pos.y - 1.2 -- feet level + local node_feet = minetest.get_node(pos).name + -- is player inside a hot node? + for _, row in pairs(armor.fire_nodes) do + -- check fire protection, if not enough then get hurt + if row[1] == node_head or row[1] == node_feet then + if fire_damage == true then + armor:punch(player, "fire") + last_punch_time[name] = minetest.get_gametime() + fire_damage = false + end + if hp > 0 and armor.def[name].fire < row[2] then + hp = hp - row[3] * armor.config.update_time + player:set_hp(hp) + break + end + end + end + end + end + armor.timer = 0 + end) +end diff --git a/mods/3d_armor/models/3d_armor_character.b3d b/mods/3d_armor/models/3d_armor_character.b3d new file mode 100644 index 0000000..1287690 Binary files /dev/null and b/mods/3d_armor/models/3d_armor_character.b3d differ diff --git a/mods/3d_armor/models/3d_armor_character.blend b/mods/3d_armor/models/3d_armor_character.blend new file mode 100644 index 0000000..5996296 Binary files /dev/null and b/mods/3d_armor/models/3d_armor_character.blend differ diff --git a/mods/3d_armor/textures/3d_armor_boots_admin.png b/mods/3d_armor/textures/3d_armor_boots_admin.png new file mode 100644 index 0000000..23be004 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_admin_preview.png b/mods/3d_armor/textures/3d_armor_boots_admin_preview.png new file mode 100644 index 0000000..77acce6 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_admin_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_bronze.png b/mods/3d_armor/textures/3d_armor_boots_bronze.png new file mode 100644 index 0000000..2f4fd83 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_bronze_preview.png b/mods/3d_armor/textures/3d_armor_boots_bronze_preview.png new file mode 100644 index 0000000..1f83af3 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_bronze_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_cactus.png b/mods/3d_armor/textures/3d_armor_boots_cactus.png new file mode 100644 index 0000000..f370644 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_cactus_preview.png b/mods/3d_armor/textures/3d_armor_boots_cactus_preview.png new file mode 100644 index 0000000..e4cbf13 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_cactus_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_crystal.png b/mods/3d_armor/textures/3d_armor_boots_crystal.png new file mode 100644 index 0000000..3ca8899 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_crystal_preview.png b/mods/3d_armor/textures/3d_armor_boots_crystal_preview.png new file mode 100644 index 0000000..0c6b3e4 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_crystal_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_diamond.png b/mods/3d_armor/textures/3d_armor_boots_diamond.png new file mode 100644 index 0000000..ef40206 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_diamond_preview.png b/mods/3d_armor/textures/3d_armor_boots_diamond_preview.png new file mode 100644 index 0000000..7575fbd Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_diamond_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_gold.png b/mods/3d_armor/textures/3d_armor_boots_gold.png new file mode 100644 index 0000000..f431d9b Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_gold_preview.png b/mods/3d_armor/textures/3d_armor_boots_gold_preview.png new file mode 100644 index 0000000..9daae14 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_gold_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_mithril.png b/mods/3d_armor/textures/3d_armor_boots_mithril.png new file mode 100644 index 0000000..b6c65d6 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_mithril_preview.png b/mods/3d_armor/textures/3d_armor_boots_mithril_preview.png new file mode 100644 index 0000000..21de8c1 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_mithril_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_steel.png b/mods/3d_armor/textures/3d_armor_boots_steel.png new file mode 100644 index 0000000..72ec88b Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_steel_preview.png b/mods/3d_armor/textures/3d_armor_boots_steel_preview.png new file mode 100644 index 0000000..170d094 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_steel_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_wood.png b/mods/3d_armor/textures/3d_armor_boots_wood.png new file mode 100644 index 0000000..411ce9c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_boots_wood_preview.png b/mods/3d_armor/textures/3d_armor_boots_wood_preview.png new file mode 100644 index 0000000..d9f192c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_boots_wood_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_admin.png b/mods/3d_armor/textures/3d_armor_chestplate_admin.png new file mode 100644 index 0000000..a17d0a4 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_admin_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_admin_preview.png new file mode 100644 index 0000000..5395810 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_admin_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_bronze.png b/mods/3d_armor/textures/3d_armor_chestplate_bronze.png new file mode 100644 index 0000000..ac43ddb Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_bronze_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_bronze_preview.png new file mode 100644 index 0000000..ab1d1ce Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_bronze_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_cactus.png b/mods/3d_armor/textures/3d_armor_chestplate_cactus.png new file mode 100644 index 0000000..0dd7eb0 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_cactus_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_cactus_preview.png new file mode 100644 index 0000000..9523ef7 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_cactus_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_crystal.png b/mods/3d_armor/textures/3d_armor_chestplate_crystal.png new file mode 100644 index 0000000..e4981b1 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_crystal_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_crystal_preview.png new file mode 100644 index 0000000..801dc2a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_crystal_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_diamond.png b/mods/3d_armor/textures/3d_armor_chestplate_diamond.png new file mode 100644 index 0000000..3538496 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_diamond_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_diamond_preview.png new file mode 100644 index 0000000..92909b3 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_diamond_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_gold.png b/mods/3d_armor/textures/3d_armor_chestplate_gold.png new file mode 100644 index 0000000..cc3e910 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_gold_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_gold_preview.png new file mode 100644 index 0000000..df47bf0 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_gold_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_mithril.png b/mods/3d_armor/textures/3d_armor_chestplate_mithril.png new file mode 100644 index 0000000..b06b2a8 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_mithril_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_mithril_preview.png new file mode 100644 index 0000000..4859295 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_mithril_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_steel.png b/mods/3d_armor/textures/3d_armor_chestplate_steel.png new file mode 100644 index 0000000..bccb99d Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_steel_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_steel_preview.png new file mode 100644 index 0000000..804e785 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_steel_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_wood.png b/mods/3d_armor/textures/3d_armor_chestplate_wood.png new file mode 100644 index 0000000..bae4817 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_chestplate_wood_preview.png b/mods/3d_armor/textures/3d_armor_chestplate_wood_preview.png new file mode 100644 index 0000000..8f75f26 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_chestplate_wood_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_admin.png b/mods/3d_armor/textures/3d_armor_helmet_admin.png new file mode 100644 index 0000000..0a04251 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_admin_preview.png b/mods/3d_armor/textures/3d_armor_helmet_admin_preview.png new file mode 100644 index 0000000..9f44921 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_admin_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_bronze.png b/mods/3d_armor/textures/3d_armor_helmet_bronze.png new file mode 100644 index 0000000..7ef5595 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_bronze_preview.png b/mods/3d_armor/textures/3d_armor_helmet_bronze_preview.png new file mode 100644 index 0000000..9a62f82 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_bronze_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_cactus.png b/mods/3d_armor/textures/3d_armor_helmet_cactus.png new file mode 100644 index 0000000..e48ec34 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_cactus_preview.png b/mods/3d_armor/textures/3d_armor_helmet_cactus_preview.png new file mode 100644 index 0000000..c8be84a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_cactus_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_crystal.png b/mods/3d_armor/textures/3d_armor_helmet_crystal.png new file mode 100644 index 0000000..e63a63f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_crystal_preview.png b/mods/3d_armor/textures/3d_armor_helmet_crystal_preview.png new file mode 100644 index 0000000..dddbbc0 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_crystal_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_diamond.png b/mods/3d_armor/textures/3d_armor_helmet_diamond.png new file mode 100644 index 0000000..611dc9f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_diamond_preview.png b/mods/3d_armor/textures/3d_armor_helmet_diamond_preview.png new file mode 100644 index 0000000..ed52aed Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_diamond_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_gold.png b/mods/3d_armor/textures/3d_armor_helmet_gold.png new file mode 100644 index 0000000..24da53b Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_gold_preview.png b/mods/3d_armor/textures/3d_armor_helmet_gold_preview.png new file mode 100644 index 0000000..d4d9d0c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_gold_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_mithril.png b/mods/3d_armor/textures/3d_armor_helmet_mithril.png new file mode 100644 index 0000000..57e579e Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_mithril_preview.png b/mods/3d_armor/textures/3d_armor_helmet_mithril_preview.png new file mode 100644 index 0000000..be50523 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_mithril_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_steel.png b/mods/3d_armor/textures/3d_armor_helmet_steel.png new file mode 100644 index 0000000..8d21e8a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_steel_preview.png b/mods/3d_armor/textures/3d_armor_helmet_steel_preview.png new file mode 100644 index 0000000..774d284 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_steel_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_wood.png b/mods/3d_armor/textures/3d_armor_helmet_wood.png new file mode 100644 index 0000000..01e243a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_helmet_wood_preview.png b/mods/3d_armor/textures/3d_armor_helmet_wood_preview.png new file mode 100644 index 0000000..0e0c3b1 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_helmet_wood_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_admin.png b/mods/3d_armor/textures/3d_armor_inv_boots_admin.png new file mode 100644 index 0000000..69fc00a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_bronze.png b/mods/3d_armor/textures/3d_armor_inv_boots_bronze.png new file mode 100644 index 0000000..448f41d Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_cactus.png b/mods/3d_armor/textures/3d_armor_inv_boots_cactus.png new file mode 100644 index 0000000..3f57f22 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_crystal.png b/mods/3d_armor/textures/3d_armor_inv_boots_crystal.png new file mode 100644 index 0000000..e311893 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_diamond.png b/mods/3d_armor/textures/3d_armor_inv_boots_diamond.png new file mode 100644 index 0000000..0a866e7 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_gold.png b/mods/3d_armor/textures/3d_armor_inv_boots_gold.png new file mode 100644 index 0000000..55d78b7 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_mithril.png b/mods/3d_armor/textures/3d_armor_inv_boots_mithril.png new file mode 100644 index 0000000..00c26f9 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_steel.png b/mods/3d_armor/textures/3d_armor_inv_boots_steel.png new file mode 100644 index 0000000..82fc591 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_boots_wood.png b/mods/3d_armor/textures/3d_armor_inv_boots_wood.png new file mode 100644 index 0000000..53bb557 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_boots_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_admin.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_admin.png new file mode 100644 index 0000000..dafef2c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_bronze.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_bronze.png new file mode 100644 index 0000000..8fc2f17 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_cactus.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_cactus.png new file mode 100644 index 0000000..7f5bc70 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_crystal.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_crystal.png new file mode 100644 index 0000000..b9593bf Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_diamond.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_diamond.png new file mode 100644 index 0000000..f5ca3aa Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_gold.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_gold.png new file mode 100644 index 0000000..efe76ca Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_mithril.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_mithril.png new file mode 100644 index 0000000..6ca9231 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_steel.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_steel.png new file mode 100644 index 0000000..47ef4f2 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_chestplate_wood.png b/mods/3d_armor/textures/3d_armor_inv_chestplate_wood.png new file mode 100644 index 0000000..dac3b06 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_chestplate_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_admin.png b/mods/3d_armor/textures/3d_armor_inv_helmet_admin.png new file mode 100644 index 0000000..494cc84 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_bronze.png b/mods/3d_armor/textures/3d_armor_inv_helmet_bronze.png new file mode 100644 index 0000000..c0028dd Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_cactus.png b/mods/3d_armor/textures/3d_armor_inv_helmet_cactus.png new file mode 100644 index 0000000..10a2b39 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_crystal.png b/mods/3d_armor/textures/3d_armor_inv_helmet_crystal.png new file mode 100644 index 0000000..565383e Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_diamond.png b/mods/3d_armor/textures/3d_armor_inv_helmet_diamond.png new file mode 100644 index 0000000..6df57bd Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_gold.png b/mods/3d_armor/textures/3d_armor_inv_helmet_gold.png new file mode 100644 index 0000000..6820d8f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_mithril.png b/mods/3d_armor/textures/3d_armor_inv_helmet_mithril.png new file mode 100644 index 0000000..ce4e910 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_steel.png b/mods/3d_armor/textures/3d_armor_inv_helmet_steel.png new file mode 100644 index 0000000..1c8bfe8 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_helmet_wood.png b/mods/3d_armor/textures/3d_armor_inv_helmet_wood.png new file mode 100644 index 0000000..fbb3e3f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_helmet_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_admin.png b/mods/3d_armor/textures/3d_armor_inv_leggings_admin.png new file mode 100644 index 0000000..e652ef1 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_bronze.png b/mods/3d_armor/textures/3d_armor_inv_leggings_bronze.png new file mode 100644 index 0000000..f194f9f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_cactus.png b/mods/3d_armor/textures/3d_armor_inv_leggings_cactus.png new file mode 100644 index 0000000..f7c1a28 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_crystal.png b/mods/3d_armor/textures/3d_armor_inv_leggings_crystal.png new file mode 100644 index 0000000..d466b20 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_diamond.png b/mods/3d_armor/textures/3d_armor_inv_leggings_diamond.png new file mode 100644 index 0000000..c4cd85c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_gold.png b/mods/3d_armor/textures/3d_armor_inv_leggings_gold.png new file mode 100644 index 0000000..2e4b244 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_mithril.png b/mods/3d_armor/textures/3d_armor_inv_leggings_mithril.png new file mode 100644 index 0000000..ffe972c Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_steel.png b/mods/3d_armor/textures/3d_armor_inv_leggings_steel.png new file mode 100644 index 0000000..1ca9975 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_inv_leggings_wood.png b/mods/3d_armor/textures/3d_armor_inv_leggings_wood.png new file mode 100644 index 0000000..9e73b72 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_inv_leggings_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_admin.png b/mods/3d_armor/textures/3d_armor_leggings_admin.png new file mode 100644 index 0000000..bedfbc1 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_admin.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_admin_preview.png b/mods/3d_armor/textures/3d_armor_leggings_admin_preview.png new file mode 100644 index 0000000..1d32265 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_admin_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_bronze.png b/mods/3d_armor/textures/3d_armor_leggings_bronze.png new file mode 100644 index 0000000..bcba372 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_bronze.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_bronze_preview.png b/mods/3d_armor/textures/3d_armor_leggings_bronze_preview.png new file mode 100644 index 0000000..c378148 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_bronze_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_cactus.png b/mods/3d_armor/textures/3d_armor_leggings_cactus.png new file mode 100644 index 0000000..88aa32d Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_cactus.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_cactus_preview.png b/mods/3d_armor/textures/3d_armor_leggings_cactus_preview.png new file mode 100644 index 0000000..9dab482 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_cactus_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_crystal.png b/mods/3d_armor/textures/3d_armor_leggings_crystal.png new file mode 100644 index 0000000..754bd0f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_crystal.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_crystal_preview.png b/mods/3d_armor/textures/3d_armor_leggings_crystal_preview.png new file mode 100644 index 0000000..7808496 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_crystal_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_diamond.png b/mods/3d_armor/textures/3d_armor_leggings_diamond.png new file mode 100644 index 0000000..a57cf07 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_diamond.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_diamond_preview.png b/mods/3d_armor/textures/3d_armor_leggings_diamond_preview.png new file mode 100644 index 0000000..84976c4 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_diamond_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_gold.png b/mods/3d_armor/textures/3d_armor_leggings_gold.png new file mode 100644 index 0000000..dfdd094 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_gold.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_gold_preview.png b/mods/3d_armor/textures/3d_armor_leggings_gold_preview.png new file mode 100644 index 0000000..ff2e3d0 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_gold_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_mithril.png b/mods/3d_armor/textures/3d_armor_leggings_mithril.png new file mode 100644 index 0000000..2143572 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_mithril.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_mithril_preview.png b/mods/3d_armor/textures/3d_armor_leggings_mithril_preview.png new file mode 100644 index 0000000..178054a Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_mithril_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_steel.png b/mods/3d_armor/textures/3d_armor_leggings_steel.png new file mode 100644 index 0000000..cca4e31 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_steel.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_steel_preview.png b/mods/3d_armor/textures/3d_armor_leggings_steel_preview.png new file mode 100644 index 0000000..dbcfcf2 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_steel_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_wood.png b/mods/3d_armor/textures/3d_armor_leggings_wood.png new file mode 100644 index 0000000..eb61034 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_wood.png differ diff --git a/mods/3d_armor/textures/3d_armor_leggings_wood_preview.png b/mods/3d_armor/textures/3d_armor_leggings_wood_preview.png new file mode 100644 index 0000000..1545b4b Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_leggings_wood_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_preview.png b/mods/3d_armor/textures/3d_armor_preview.png new file mode 100644 index 0000000..82a0ae4 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_preview.png differ diff --git a/mods/3d_armor/textures/3d_armor_trans.png b/mods/3d_armor/textures/3d_armor_trans.png new file mode 100644 index 0000000..4a31242 Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_trans.png differ diff --git a/mods/3d_armor/textures/3d_armor_ui_form.png b/mods/3d_armor/textures/3d_armor_ui_form.png new file mode 100644 index 0000000..993809f Binary files /dev/null and b/mods/3d_armor/textures/3d_armor_ui_form.png differ diff --git a/mods/3d_armor/textures/inventory_plus_armor.png b/mods/3d_armor/textures/inventory_plus_armor.png new file mode 100644 index 0000000..f317c70 Binary files /dev/null and b/mods/3d_armor/textures/inventory_plus_armor.png differ diff --git a/mods/3d_armor/textures/preview_index.txt b/mods/3d_armor/textures/preview_index.txt new file mode 100644 index 0000000..9e2fe9d --- /dev/null +++ b/mods/3d_armor/textures/preview_index.txt @@ -0,0 +1,44 @@ +3d_armor/textures/3d_armor_helmet_wood.png:head +3d_armor/textures/3d_armor_chestplate_wood.png:torso +3d_armor/textures/3d_armor_leggings_wood.png:legs +3d_armor/textures/3d_armor_boots_wood.png:feet + +3d_armor/textures/3d_armor_helmet_cactus.png:head +3d_armor/textures/3d_armor_chestplate_cactus.png:torso +3d_armor/textures/3d_armor_leggings_cactus.png:legs +3d_armor/textures/3d_armor_boots_cactus.png:feet + +3d_armor/textures/3d_armor_helmet_steel.png:head +3d_armor/textures/3d_armor_chestplate_steel.png:torso +3d_armor/textures/3d_armor_leggings_steel.png:legs +3d_armor/textures/3d_armor_boots_steel.png:feet + +3d_armor/textures/3d_armor_helmet_bronze.png:head +3d_armor/textures/3d_armor_chestplate_bronze.png:torso +3d_armor/textures/3d_armor_leggings_bronze.png:legs +3d_armor/textures/3d_armor_boots_bronze.png:feet + +3d_armor/textures/3d_armor_helmet_gold.png:head +3d_armor/textures/3d_armor_chestplate_gold.png:torso +3d_armor/textures/3d_armor_leggings_gold.png:legs +3d_armor/textures/3d_armor_boots_gold.png:feet + +3d_armor/textures/3d_armor_helmet_diamond.png:head +3d_armor/textures/3d_armor_chestplate_diamond.png:torso +3d_armor/textures/3d_armor_leggings_diamond.png:legs +3d_armor/textures/3d_armor_boots_diamond.png:feet + +3d_armor/textures/3d_armor_helmet_mithril.png:head +3d_armor/textures/3d_armor_chestplate_mithril.png:torso +3d_armor/textures/3d_armor_leggings_mithril.png:legs +3d_armor/textures/3d_armor_boots_mithril.png:feet + +3d_armor/textures/3d_armor_helmet_crystal.png:head +3d_armor/textures/3d_armor_chestplate_crystal.png:torso +3d_armor/textures/3d_armor_leggings_crystal.png:legs +3d_armor/textures/3d_armor_boots_crystal.png:feet + +3d_armor/textures/3d_armor_helmet_admin.png:head +3d_armor/textures/3d_armor_chestplate_admin.png:torso +3d_armor/textures/3d_armor_leggings_admin.png:legs +3d_armor/textures/3d_armor_boots_admin.png:feet diff --git a/mods/3d_armor_stand/LICENSE.txt b/mods/3d_armor_stand/LICENSE.txt new file mode 100644 index 0000000..65f46c8 --- /dev/null +++ b/mods/3d_armor_stand/LICENSE.txt @@ -0,0 +1,22 @@ +[mod] 3d Armor Stand [3d_armor_stand] +===================================== + +License Source Code: (C) 2016-2017 Stuart Jones - LGPL v2.1 + +Lecense Models: (C) 2016-2017 Stuart Jones - CC BY-SA 3.0 + +UV model mapping by tobyplowy(aka toby109tt) + +License Textures: + +3d_armor_stand.png +3d_armor_stand_locked.png + +(C) 2017 tobyplowy - CC BY-SA 3.0 + +3d_armor_stand_feet.png +3d_armor_stand_head.png +3d_armor_stand_legs.png +3d_armor_stand_torso.png + +(C) 2016-2017 Stuart Jones - CC BY-SA 3.0 diff --git a/mods/3d_armor_stand/README.txt b/mods/3d_armor_stand/README.txt new file mode 100644 index 0000000..6a98ab9 --- /dev/null +++ b/mods/3d_armor_stand/README.txt @@ -0,0 +1,21 @@ +[mod] 3d Armor Stand [3d_armor_stand] +===================================== + +Depends: 3d_armor + +Adds a chest-like armor stand for armor storage and display. + +Crafting +-------- + +F = Wooden Fence [default:fence_wood] +S = Steel Ingot [default:steel_ingot] + ++---+---+---+ +| | F | | ++---+---+---+ +| | F | | ++---+---+---+ +| S | S | S | ++---+---+---+ + diff --git a/mods/3d_armor_stand/depends.txt b/mods/3d_armor_stand/depends.txt new file mode 100644 index 0000000..3b70bec --- /dev/null +++ b/mods/3d_armor_stand/depends.txt @@ -0,0 +1,2 @@ +3d_armor +jas0 diff --git a/mods/3d_armor_stand/init.lua b/mods/3d_armor_stand/init.lua new file mode 100644 index 0000000..5a985d8 --- /dev/null +++ b/mods/3d_armor_stand/init.lua @@ -0,0 +1,367 @@ +local S = function(s) return s end +if minetest.global_exists("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + S = intllib.make_gettext_pair() + else + -- Old method using text files. + S = intllib.Getter() + end +end +-- formspec = apply armor screen, followed by: +-- armor crafting? (a la clothing/loom) + apply player armor. +-- and second screen: applying armor to stand. +local armor_stand_formspec = "size[8,7]" .. + default.get_hotbar_bg(0, 3) .. + jas0.exit_button() .. + "button_exit[0,0;2,1;player_armor;Player Armor]" .. + "list[current_name;armor_head;3,0.5;1,1;]" .. + "list[current_name;armor_torso;4,0.5;1,1;]" .. + "list[current_name;armor_legs;3,1.5;1,1;]" .. + "list[current_name;armor_feet;4,1.5;1,1;]" .. + "image[3,0.5;1,1;3d_armor_stand_head.png]" .. + "image[4,0.5;1,1;3d_armor_stand_torso.png]" .. + "image[3,1.5;1,1;3d_armor_stand_legs.png]" .. + "image[4,1.5;1,1;3d_armor_stand_feet.png]" .. + "list[current_player;main;0,3;8,1;]" .. + "list[current_player;main;0,4.25;8,3;8]" .. +"" + +local elements = {"head", "torso", "legs", "feet"} + +local function drop_armor(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, element in pairs(elements) do + local stack = inv:get_stack("armor_"..element, 1) + if stack and stack:get_count() > 0 then + armor.drop_armor(pos, stack) + inv:set_stack("armor_"..element, 1, nil) + end + end +end + +local function get_stand_object(pos) + local object = nil + local objects = minetest.get_objects_inside_radius(pos, 0.5) or {} + for _, obj in pairs(objects) do + local ent = obj:get_luaentity() + if ent then + if ent.name == "3d_armor_stand:armor_entity" then + -- Remove duplicates + if object then + obj:remove() + else + object = obj + end + end + end + end + return object +end + +local function update_entity(pos) + local node = minetest.get_node(pos) + local object = get_stand_object(pos) + if object then + if not string.find(node.name, "3d_armor_stand:") then + object:remove() + return + end + else + object = minetest.add_entity(pos, "3d_armor_stand:armor_entity") + end + if object then + local texture = "3d_armor_trans.png" + local textures = {} + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local yaw = 0 + if inv then + for _, element in pairs(elements) do + local stack = inv:get_stack("armor_"..element, 1) + if stack:get_count() == 1 then + local item = stack:get_name() or "" + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups["armor_"..element] then + local texture = def.texture or item:gsub("%:", "_") + table.insert(textures, texture..".png") + end + end + end + end + if #textures > 0 then + texture = table.concat(textures, "^") + end + if node.param2 then + local rot = node.param2 % 4 + if rot == 1 then + yaw = 3 * math.pi / 2 + elseif rot == 2 then + yaw = math.pi + elseif rot == 3 then + yaw = math.pi / 2 + end + end + object:setyaw(yaw) + object:set_properties({textures={texture}}) + end +end + +local function has_locked_armor_stand_privilege(meta, player) + local name = "" + if player then + if minetest.check_player_privs(player, "protection_bypass") then + return true + end + name = player:get_player_name() + end + if name ~= meta:get_string("owner") then + return false + end + return true +end + +local function add_hidden_node(pos, player) + local p = {x=pos.x, y=pos.y + 1, z=pos.z} + local name = player:get_player_name() + local node = minetest.get_node(p) + if node.name == "air" and not minetest.is_protected(pos, name) then + minetest.set_node(p, {name="3d_armor_stand:top"}) + end +end + +local function remove_hidden_node(pos) + local p = {x=pos.x, y=pos.y + 1, z=pos.z} + local node = minetest.get_node(p) + if node.name == "3d_armor_stand:top" then + minetest.remove_node(p) + end +end + +minetest.register_node("3d_armor_stand:top", { + description = S("Armor stand top"), + paramtype = "light", + drawtype = "plantlike", + sunlight_propagates = true, + walkable = true, + pointable = false, + diggable = false, + buildable_to = false, + drop = "", + groups = {not_in_creative_inventory = 1}, + on_blast = function() end, + tiles = {"3d_armor_trans.png"}, +}) + +minetest.register_node("3d_armor_stand:armor_stand", { + description = S("Armor stand"), + drawtype = "mesh", + mesh = "3d_armor_stand.obj", + tiles = {"3d_armor_stand.png"}, + paramtype = "light", + paramtype2 = "facedir", + walkable = false, + selection_box = { + type = "fixed", + fixed = { + {-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25}, + {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}, + }, + }, + groups = {choppy=2, oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", armor_stand_formspec) + meta:set_string("infotext", "Armor Stand") + local inv = meta:get_inventory() + for _, element in pairs(elements) do + inv:set_size("armor_"..element, 1) + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, element in pairs(elements) do + if not inv:is_empty("armor_"..element) then + return false + end + end + return true + end, + after_place_node = function(pos, placer) + minetest.add_entity(pos, "3d_armor_stand:armor_entity") + add_hidden_node(pos, placer) + end, + allow_metadata_inventory_put = function(pos, listname, index, stack) + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups[listname] then + return 1 + end + return 0 + end, + allow_metadata_inventory_move = function(pos) + return 0 + end, + on_metadata_inventory_put = function(pos) + update_entity(pos) + end, + on_metadata_inventory_take = function(pos) + update_entity(pos) + end, + after_destruct = function(pos) + update_entity(pos) + remove_hidden_node(pos) + end, + on_blast = function(pos) + drop_armor(pos) + armor.drop_armor(pos, "3d_armor_stand:armor_stand") + minetest.remove_node(pos) + end, + on_receive_fields = function(pos, formname, fields, sender) + if fields.player_armor then + minetest.after(0.1, function() + local name = sender:get_player_name() + minetest.show_formspec(name, "3d_armor:player_armor", + "size[8,5.25]" .. + jas0.exit_button() .. + "list[detached:" .. name .. "_armor;armor;1,0;6,1]" .. + "list[current_player;main;0,1.34;8,1]" .. + "list[current_player;main;0,2.5;8,3;8]" .. + "listring[detached:" .. name .. "_armor;armor]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 1.34) .. + "") + end) + end + end, +}) + +minetest.register_node("3d_armor_stand:locked_armor_stand", { + description = S("Locked Armor stand"), + drawtype = "mesh", + mesh = "3d_armor_stand.obj", + tiles = {"3d_armor_stand_locked.png"}, + paramtype = "light", + paramtype2 = "facedir", + walkable = false, + selection_box = { + type = "fixed", + fixed = { + {-0.25, -0.4375, -0.25, 0.25, 1.4, 0.25}, + {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}, + }, + }, + groups = {choppy=2, oddly_breakable_by_hand=2}, + sounds = default.node_sound_wood_defaults(), + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", armor_stand_formspec) + meta:set_string("infotext", "Armor Stand") + meta:set_string("owner", "") + local inv = meta:get_inventory() + for _, element in pairs(elements) do + inv:set_size("armor_"..element, 1) + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + for _, element in pairs(elements) do + if not inv:is_empty("armor_"..element) then + return false + end + end + return true + end, + after_place_node = function(pos, placer) + minetest.add_entity(pos, "3d_armor_stand:armor_entity") + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name() or "") + meta:set_string("infotext", "Armor Stand (owned by " .. + meta:get_string("owner") .. ")") + add_hidden_node(pos, placer) + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if not has_locked_armor_stand_privilege(meta, player) then + return 0 + end + local def = stack:get_definition() or {} + local groups = def.groups or {} + if groups[listname] then + return 1 + end + return 0 + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if not has_locked_armor_stand_privilege(meta, player) then + return 0 + end + return stack:get_count() + end, + allow_metadata_inventory_move = function(pos) + return 0 + end, + on_metadata_inventory_put = function(pos) + update_entity(pos) + end, + on_metadata_inventory_take = function(pos) + update_entity(pos) + end, + after_destruct = function(pos) + update_entity(pos) + remove_hidden_node(pos) + end, + on_blast = function(pos) + -- Not affected by TNT + end, +}) + +minetest.register_entity("3d_armor_stand:armor_entity", { + physical = true, + visual = "mesh", + mesh = "3d_armor_entity.obj", + visual_size = {x=1, y=1}, + collisionbox = {0,0,0,0,0,0}, + textures = {"3d_armor_trans.png"}, + pos = nil, + timer = 0, + on_activate = function(self) + local pos = self.object:getpos() + if pos then + self.pos = vector.round(pos) + update_entity(pos) + end + end, + on_blast = function(self, damage) + local drops = {} + local node = minetest.get_node(self.pos) + if node.name == "3d_armor_stand:armor_stand" then + drop_armor(self.pos) + self.object:remove() + end + return false, false, drops + end, +}) + +minetest.register_craft({ + output = "3d_armor_stand:armor_stand", + recipe = { + {"", "group:fence", ""}, + {"", "group:fence", ""}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + } +}) + +minetest.register_craft({ + output = "3d_armor_stand:locked_armor_stand", + recipe = { + {"3d_armor_stand:armor_stand", "default:steel_ingot"}, + } +}) + diff --git a/mods/3d_armor_stand/models/3d_armor_entity.obj b/mods/3d_armor_stand/models/3d_armor_entity.obj new file mode 100644 index 0000000..052f692 --- /dev/null +++ b/mods/3d_armor_stand/models/3d_armor_entity.obj @@ -0,0 +1,193 @@ +# Blender v2.73 (sub 0) OBJ File: '3d_armor_entity_3.blend' +# www.blender.org +mtllib 3d_armor_entity.mtl +o Player_Cube +v 2.200000 9.763893 1.200000 +v 2.200000 9.763893 -1.200000 +v 2.200000 2.663871 1.200000 +v 2.200000 2.663871 -1.200000 +v -2.200000 9.763893 -1.200000 +v -2.200000 9.763893 1.200000 +v -2.200000 2.663871 -1.200000 +v -2.200000 2.663871 1.200000 +v 2.300000 13.863962 2.300000 +v 2.300000 13.863962 -2.300000 +v 2.300000 9.263885 2.300000 +v 2.300000 9.263885 -2.300000 +v -2.300000 13.863962 -2.300000 +v -2.300000 13.863962 2.300000 +v -2.300000 9.263885 -2.300000 +v -2.300000 9.263885 2.300000 +v -2.322686 2.473175 -1.300000 +v -2.322686 2.473175 1.300000 +v -4.713554 2.682348 1.300000 +v -4.713554 2.682348 -1.300000 +v -1.686446 9.745432 -1.300000 +v -1.686446 9.745432 1.300000 +v -4.077313 9.954605 1.300000 +v -4.077313 9.954605 -1.300000 +v 4.077313 9.954605 -1.300000 +v 4.077313 9.954605 1.300000 +v 1.686446 9.745432 1.300000 +v 1.686446 9.745432 -1.300000 +v 4.713554 2.682348 -1.300000 +v 4.713554 2.682348 1.300000 +v 2.322686 2.473175 1.300000 +v 2.322686 2.473175 -1.300000 +v 0.139099 2.938947 -1.200000 +v 0.139099 2.938947 1.200000 +v 0.261266 -4.059988 1.200000 +v 0.261266 -4.059988 -1.200000 +v 2.660901 -4.018101 1.190000 +v 2.660901 -4.018101 -1.210000 +v 2.538733 2.980834 1.190000 +v 2.538733 2.980834 -1.210000 +v -0.139099 2.938947 -1.200000 +v -0.139099 2.938947 1.200000 +v -0.261266 -4.059988 1.200000 +v -0.261266 -4.059988 -1.200000 +v -2.538734 2.980834 -1.210000 +v -2.538734 2.980834 1.190000 +v -2.660901 -4.018101 -1.210000 +v -2.660901 -4.018101 1.190000 +v -2.799999 -4.387500 1.390000 +v -2.799999 -4.387500 -1.410000 +v -2.800000 -0.812499 1.390000 +v -2.800000 -0.812499 -1.410000 +v -0.000000 -4.387500 -1.400000 +v -0.000000 -4.387500 1.400000 +v -0.000000 -0.812499 1.400000 +v -0.000000 -0.812499 -1.400000 +v 2.800000 -0.812499 -1.410000 +v 2.800000 -0.812499 1.390000 +v 2.799999 -4.387500 -1.410000 +v 2.799999 -4.387500 1.390000 +v 0.000000 -4.387500 -1.400000 +v 0.000000 -4.387500 1.400000 +v 0.000000 -0.812499 1.400000 +v 0.000000 -0.812499 -1.400000 +v 2.267006 13.830965 2.267006 +v 2.267006 13.830965 -2.267006 +v 2.267006 9.296881 2.267006 +v 2.267006 9.296881 -2.267006 +v -2.267006 13.830965 -2.267006 +v -2.267006 13.830965 2.267006 +v -2.267006 9.296881 -2.267006 +v -2.267006 9.296881 2.267006 +vt 0.250000 0.375000 +vt 0.250000 0.000000 +vt 0.312500 0.000000 +vt 0.312500 0.375000 +vt 0.437500 0.375000 +vt 0.437500 0.500000 +vt 0.312500 0.500000 +vt 0.562500 0.375000 +vt 0.562500 0.500000 +vt 0.437500 0.000000 +vt 0.500000 0.000000 +vt 0.500000 0.375000 +vt 0.625000 0.000000 +vt 0.625000 0.375000 +vt 0.500000 0.750000 +vt 0.500000 0.500000 +vt 0.625000 0.500000 +vt 0.625000 0.750000 +vt 0.750000 0.750000 +vt 0.750000 1.000000 +vt 0.625000 1.000000 +vt 0.875000 0.750000 +vt 0.875000 1.000000 +vt 0.750000 0.500000 +vt 0.875000 0.500000 +vt 1.000000 0.750000 +vt 1.000000 0.500000 +vt 0.750000 0.375000 +vt 0.812500 0.500000 +vt 0.812500 0.375000 +vt 0.687500 0.375000 +vt 0.687500 0.500000 +vt 0.687500 0.000000 +vt 0.750000 0.000000 +vt 0.812500 0.000000 +vt 0.875000 0.375000 +vt 0.875000 0.000000 +vt 0.125000 0.375000 +vt 0.062500 0.375000 +vt 0.062500 0.500000 +vt 0.125000 0.500000 +vt 0.187500 0.375000 +vt 0.187500 0.500000 +vt 0.000000 0.375000 +vt 0.000000 0.000000 +vt 0.062500 0.000000 +vt 0.187500 0.000000 +vt 0.125000 0.000000 +vt 0.437500 0.875000 +vt 0.437500 1.000000 +vt 0.375000 1.000000 +vt 0.375000 0.875000 +vt 0.250000 0.875000 +vt 0.312500 0.875000 +vt 0.312500 0.656250 +vt 0.250000 0.656250 +vt 0.500000 0.875000 +vt 0.437500 0.656250 +vt 0.500000 0.656250 +vt 0.375000 0.656250 +vt 0.312500 1.000000 +usemtl Armor +s off +f 1/1 3/2 4/3 2/4 +f 5/5 6/6 1/7 2/4 +f 8/6 7/5 4/8 3/9 +f 5/5 2/4 4/3 7/10 +f 7/10 8/11 6/12 5/5 +f 8/11 3/13 1/14 6/12 +f 9/15 11/16 12/17 10/18 +f 13/19 14/20 9/21 10/18 +f 12/22 11/23 16/20 15/19 +f 13/19 10/18 12/17 15/24 +f 14/22 13/19 15/24 16/25 +f 9/26 14/22 16/25 11/27 +f 17/28 18/24 19/29 20/30 +f 24/31 23/32 22/24 21/28 +f 23/31 24/14 20/13 19/33 +f 24/31 21/28 17/34 20/33 +f 21/28 22/30 18/35 17/34 +f 22/30 23/36 19/37 18/35 +f 27/30 31/35 30/37 26/36 +f 28/28 32/34 31/35 27/30 +f 25/31 29/33 32/34 28/28 +f 26/31 30/33 29/13 25/14 +f 25/31 28/28 27/24 26/32 +f 32/28 29/30 30/29 31/24 +f 40/38 33/39 34/40 39/41 +f 36/42 38/38 37/41 35/43 +f 39/44 37/45 38/46 40/39 +f 34/1 35/2 37/47 39/42 +f 40/38 38/48 36/46 33/39 +f 33/42 36/47 35/48 34/38 +f 45/38 46/41 42/40 41/39 +f 41/42 42/38 43/48 44/47 +f 45/38 41/39 44/46 47/48 +f 42/1 46/42 48/47 43/2 +f 46/44 45/39 47/46 48/45 +f 44/42 43/43 48/41 47/38 +f 53/49 54/50 49/51 50/52 +f 51/53 52/54 50/55 49/56 +f 55/57 51/49 49/58 54/59 +f 52/52 56/54 53/55 50/60 +f 56/49 55/52 54/60 53/58 +f 52/52 51/51 55/61 56/54 +f 64/49 61/58 62/60 63/52 +f 57/52 59/60 61/55 64/54 +f 63/57 62/59 60/58 58/49 +f 58/53 60/56 59/55 57/54 +f 61/49 59/52 60/51 62/50 +f 57/52 64/54 63/61 58/51 +f 65/15 66/18 68/17 67/16 +f 69/19 66/18 65/21 70/20 +f 68/22 71/19 72/20 67/23 +f 69/19 71/24 68/17 66/18 +f 70/22 72/25 71/24 69/19 +f 65/26 67/27 72/25 70/22 diff --git a/mods/3d_armor_stand/models/3d_armor_stand.obj b/mods/3d_armor_stand/models/3d_armor_stand.obj new file mode 100644 index 0000000..0df6dc7 --- /dev/null +++ b/mods/3d_armor_stand/models/3d_armor_stand.obj @@ -0,0 +1,280 @@ +# Blender v2.72 (sub 0) OBJ File: '' +# www.blender.org +mtllib 3d_armor_stand.mtl +o Armor_Stand_Player_Cube_Stand +v 0.062500 0.125002 -0.062500 +v 0.062500 -0.437500 -0.062500 +v 0.062500 -0.437500 0.062500 +v 0.062500 0.125002 0.062500 +v -0.187500 0.250004 0.062500 +v -0.187500 0.250004 -0.062500 +v -0.250000 0.250004 -0.062500 +v -0.250000 0.250004 0.062500 +v -0.062500 -0.437500 -0.062500 +v -0.062500 -0.437500 0.062500 +v -0.187500 -0.437500 0.062500 +v -0.187500 -0.437500 -0.062500 +v -0.187500 0.125002 0.062500 +v -0.187500 0.125002 -0.062500 +v -0.187500 0.937504 0.062500 +v -0.187500 0.937504 -0.062500 +v -0.375000 0.937504 -0.062500 +v -0.375000 0.937504 0.062500 +v -0.062500 0.125002 0.062500 +v 0.187500 0.125002 -0.062500 +v 0.187500 -0.437500 -0.062500 +v -0.062500 0.125002 -0.062500 +v -0.250000 0.125007 -0.062500 +v -0.250000 0.125007 0.062500 +v 0.187500 -0.437500 0.062500 +v 0.187500 0.125002 0.062500 +v -0.062500 0.937504 0.062500 +v -0.187500 0.812504 0.062500 +v -0.062500 0.812504 0.062500 +v -0.062500 0.937504 -0.062500 +v 0.187500 0.250004 -0.062500 +v 0.187500 0.250004 0.062500 +v 0.250000 0.250004 0.062500 +v 0.250000 0.250004 -0.062500 +v 0.250000 0.125007 0.062500 +v 0.250000 0.125007 -0.062500 +v 0.187500 0.812504 0.062500 +v 0.187500 0.812504 -0.062500 +v 0.375000 0.812504 -0.062500 +v 0.375000 0.812504 0.062500 +v 0.187500 0.937504 -0.062500 +v 0.187500 0.937504 0.062500 +v 0.375000 0.937504 0.062500 +v 0.375000 0.937504 -0.062500 +v 0.062500 0.937504 -0.062500 +v 0.062500 0.937504 0.062500 +v -0.062500 0.812504 -0.062500 +v -0.187500 0.812504 -0.062500 +v 0.062500 0.812504 -0.062500 +v 0.062500 0.812504 0.062500 +v -0.375000 0.812504 -0.062500 +v -0.375000 0.812504 0.062500 +v -0.062500 0.250004 0.062500 +v 0.062500 0.250004 0.062500 +v 0.062500 0.250004 -0.062500 +v -0.062500 0.250004 -0.062500 +v -0.062500 1.312504 -0.062500 +v 0.062500 1.312504 -0.062500 +v -0.062500 1.312504 0.062500 +v 0.062500 1.312504 0.062500 +v -0.500000 -0.437500 -0.500000 +v -0.500000 -0.437500 0.500000 +v 0.500000 -0.437500 0.500000 +v 0.500000 -0.437500 -0.500000 +v -0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 -0.500000 +v 0.500000 -0.500000 0.500000 +v -0.500000 -0.500000 0.500000 +vt 0.062500 0.140625 +vt 0.062500 0.000000 +vt 0.093750 0.000000 +vt 0.093750 0.140625 +vt 0.140625 0.234375 +vt 0.140625 0.203125 +vt 0.156250 0.203125 +vt 0.156250 0.234375 +vt 0.093750 0.171875 +vt 0.062500 0.171875 +vt 0.218750 0.140625 +vt 0.187500 0.140625 +vt 0.187500 0.000000 +vt 0.218750 0.000000 +vt 0.078125 0.437500 +vt 0.078125 0.468750 +vt 0.031250 0.468750 +vt 0.031250 0.437500 +vt 0.250000 0.140625 +vt 0.250000 0.000000 +vt 0.031250 0.140625 +vt 0.031250 0.000000 +vt 0.156250 0.140625 +vt 0.156250 0.000000 +vt 0.187500 0.203125 +vt 0.156250 0.171875 +vt 0.187500 0.171875 +vt 0.125000 0.000000 +vt 0.125000 0.140625 +vt 0.000000 0.140625 +vt 0.000000 0.000000 +vt 0.328125 0.437500 +vt 0.296875 0.437500 +vt 0.296875 0.406250 +vt 0.328125 0.406250 +vt 0.109375 0.437500 +vt 0.109375 0.468750 +vt 0.046875 0.203125 +vt 0.046875 0.234375 +vt 0.031250 0.234375 +vt 0.031250 0.203125 +vt 0.000000 0.203125 +vt 0.000000 0.171875 +vt 0.031250 0.171875 +vt 0.265625 0.468750 +vt 0.265625 0.437500 +vt 0.218750 0.437500 +vt 0.218750 0.468750 +vt 0.218750 0.171875 +vt 0.171875 0.468750 +vt 0.171875 0.437500 +vt 0.078125 0.406250 +vt 0.031250 0.406250 +vt 0.140625 0.468750 +vt 0.140625 0.437500 +vt 0.140625 0.406250 +vt 0.171875 0.406250 +vt 0.109375 0.406250 +vt 0.359375 0.437500 +vt 0.359375 0.406250 +vt 0.390625 0.406250 +vt 0.390625 0.437500 +vt 0.437500 0.406250 +vt 0.437500 0.437500 +vt 0.000000 0.437500 +vt 0.000000 0.406250 +vt 0.250000 0.437500 +vt 0.218750 0.406250 +vt 0.250000 0.406250 +vt 0.359375 0.468750 +vt 0.406250 0.468750 +vt 0.406250 0.437500 +vt 0.109375 0.234375 +vt 0.078125 0.234375 +vt 0.078125 0.203125 +vt 0.109375 0.203125 +vt 0.062500 0.468750 +vt 0.062500 0.562500 +vt 0.031250 0.562500 +vt 0.328125 0.468750 +vt 0.296875 0.468750 +vt 0.062500 0.593750 +vt 0.031250 0.593750 +vt 0.093750 0.468750 +vt 0.093750 0.562500 +vt 0.125000 0.468750 +vt 0.125000 0.562500 +vt 0.000000 0.562500 +vt 0.000000 0.468750 +vt 0.078125 0.171875 +vt 0.046875 0.171875 +vt 0.265625 0.203125 +vt 0.265625 0.171875 +vt 0.296875 0.171875 +vt 0.296875 0.203125 +vt 0.265625 0.234375 +vt 0.281250 0.234375 +vt 0.281250 0.203125 +vt 0.312500 0.171875 +vt 0.312500 0.203125 +vt 0.140625 0.171875 +vt 0.171875 0.234375 +vt 0.171875 0.203125 +vt 0.109375 0.171875 +vt 0.234375 0.203125 +vt 0.203125 0.203125 +vt 0.203125 0.171875 +vt 0.234375 0.171875 +vt 0.234375 0.234375 +vt 0.203125 0.234375 +vt 0.062500 0.375000 +vt 0.062500 0.234375 +vt 0.093750 0.234375 +vt 0.093750 0.375000 +vt 0.031250 0.375000 +vt 0.125000 0.234375 +vt 0.125000 0.375000 +vt 0.000000 0.375000 +vt 0.000000 0.234375 +vt 0.218750 0.375000 +vt 0.187500 0.375000 +vt 0.187500 0.234375 +vt 0.218750 0.234375 +vt 0.250000 0.375000 +vt 0.250000 0.234375 +vt 0.156250 0.375000 +vt 0.250000 1.000000 +vt 0.250000 0.750000 +vt 0.500000 0.750000 +vt 0.500000 1.000000 +vt 0.750000 0.750000 +vt 0.750000 1.000000 +vt 0.750000 0.734375 +vt 1.000000 0.734375 +vt 1.000000 0.750000 +vt 0.000000 0.750000 +vt 0.000000 0.734375 +vt 0.250000 0.734375 +vt 0.500000 0.734375 +usemtl Stand +s off +f 1/1 2/2 3/3 4/4 +f 5/5 6/6 7/7 8/8 +f 9/1 10/4 11/9 12/10 +f 13/11 14/12 12/13 11/14 +f 15/15 16/16 17/17 18/18 +f 19/19 13/11 11/14 10/20 +f 2/2 1/1 20/21 21/22 +f 14/12 22/23 9/24 12/13 +f 8/25 7/7 23/26 24/27 +f 4/4 3/3 25/28 26/29 +f 22/23 19/29 10/28 9/24 +f 26/30 25/31 21/22 20/21 +f 27/32 15/33 28/34 29/35 +f 16/16 15/15 27/36 30/37 +f 31/38 32/39 33/40 34/41 +f 33/42 35/43 36/44 34/41 +f 37/45 38/46 39/47 40/48 +f 2/49 21/27 25/12 3/11 +f 41/50 42/51 43/47 44/48 +f 38/52 41/15 44/18 39/53 +f 41/50 45/54 46/55 42/51 +f 16/51 30/55 47/56 48/57 +f 41/15 38/52 49/58 45/36 +f 46/59 50/60 37/61 42/62 +f 42/62 37/61 40/63 43/64 +f 43/65 40/66 39/53 44/18 +f 18/67 17/47 51/68 52/69 +f 28/34 15/33 18/67 52/69 +f 16/51 48/57 51/68 17/47 +f 48/59 28/70 52/71 51/72 +f 53/73 54/74 55/75 56/76 +f 30/77 57/78 58/79 45/17 +f 50/60 46/59 27/32 29/35 +f 29/80 47/32 49/33 50/81 +f 47/56 30/55 45/36 49/58 +f 57/78 59/82 60/83 58/79 +f 27/84 59/85 57/78 30/77 +f 46/86 60/87 59/85 27/84 +f 45/17 58/79 60/88 46/89 +f 1/90 55/75 31/38 20/91 +f 54/92 4/93 26/94 32/95 +f 26/92 20/96 36/97 35/98 +f 20/91 31/38 34/41 36/44 +f 32/95 26/94 35/99 33/100 +f 6/6 14/101 23/26 7/7 +f 14/102 13/103 24/7 23/8 +f 6/6 56/76 22/104 14/101 +f 53/105 5/106 13/107 19/108 +f 13/107 5/106 8/25 24/27 +f 1/90 22/104 56/76 55/75 +f 53/105 19/108 4/93 54/92 +f 1/109 4/105 19/106 22/110 +f 49/111 55/112 54/113 50/114 +f 38/115 31/40 55/112 49/111 +f 50/114 54/113 32/116 37/117 +f 37/118 32/119 31/40 38/115 +f 28/120 48/121 6/122 5/123 +f 29/124 28/120 5/123 53/125 +f 48/121 47/126 56/8 6/122 +f 47/126 29/117 53/116 56/8 +usemtl Base +f 61/127 62/128 63/129 64/130 +f 65/129 66/131 67/132 68/130 +f 62/131 68/133 67/134 63/135 +f 63/136 67/137 66/138 64/128 +f 61/129 64/128 66/138 65/139 +f 62/131 61/129 65/139 68/133 diff --git a/mods/3d_armor_stand/models/3d_armor_stand.png b/mods/3d_armor_stand/models/3d_armor_stand.png new file mode 100644 index 0000000..aeb26de Binary files /dev/null and b/mods/3d_armor_stand/models/3d_armor_stand.png differ diff --git a/mods/3d_armor_stand/models/3d_armor_stand_locked.png b/mods/3d_armor_stand/models/3d_armor_stand_locked.png new file mode 100644 index 0000000..3ee08b4 Binary files /dev/null and b/mods/3d_armor_stand/models/3d_armor_stand_locked.png differ diff --git a/mods/3d_armor_stand/textures/3d_armor_stand_feet.png b/mods/3d_armor_stand/textures/3d_armor_stand_feet.png new file mode 100644 index 0000000..2427a60 Binary files /dev/null and b/mods/3d_armor_stand/textures/3d_armor_stand_feet.png differ diff --git a/mods/3d_armor_stand/textures/3d_armor_stand_head.png b/mods/3d_armor_stand/textures/3d_armor_stand_head.png new file mode 100644 index 0000000..5676e0b Binary files /dev/null and b/mods/3d_armor_stand/textures/3d_armor_stand_head.png differ diff --git a/mods/3d_armor_stand/textures/3d_armor_stand_legs.png b/mods/3d_armor_stand/textures/3d_armor_stand_legs.png new file mode 100644 index 0000000..1d8d4c1 Binary files /dev/null and b/mods/3d_armor_stand/textures/3d_armor_stand_legs.png differ diff --git a/mods/3d_armor_stand/textures/3d_armor_stand_torso.png b/mods/3d_armor_stand/textures/3d_armor_stand_torso.png new file mode 100644 index 0000000..ef134f8 Binary files /dev/null and b/mods/3d_armor_stand/textures/3d_armor_stand_torso.png differ diff --git a/mods/backpacks/LICENSE b/mods/backpacks/LICENSE new file mode 100644 index 0000000..71c1549 --- /dev/null +++ b/mods/backpacks/LICENSE @@ -0,0 +1,685 @@ +Backpacks mod for Glitchtest +Copyright 2018 James Stevenson +GNU GPL 3 ++----------------------------------------------------------------------+ +| Glitchtest is copyright (c) 2018 James Stevenson | +| | +| Code: GPL version 3 | +| Media: CC BY-SA 4 ++----------------------------------------------------------------------+ + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/mods/backpacks/README b/mods/backpacks/README new file mode 100644 index 0000000..0672de8 --- /dev/null +++ b/mods/backpacks/README @@ -0,0 +1,13 @@ +Backpacks mod for Glitchtest +Copyright 2018 James Stevenson +GNU GPL 3 + +Leather bag crafted with eight leather. +Colored wool backpacks crafted with eight wool. + +Backpacks can be renamed. Placing a backpack on the craftgrid and +obtaining the two leather output results in the contents of the backpack +spewing around the player. + +Backpacks must be placed on the ground, and will fall if their supporting +node is removed. diff --git a/mods/backpacks/depends.txt b/mods/backpacks/depends.txt new file mode 100644 index 0000000..9d5b402 --- /dev/null +++ b/mods/backpacks/depends.txt @@ -0,0 +1,5 @@ +jas0 +default +dye +wool +mobs? diff --git a/mods/backpacks/init.lua b/mods/backpacks/init.lua new file mode 100644 index 0000000..1aa799e --- /dev/null +++ b/mods/backpacks/init.lua @@ -0,0 +1,389 @@ +-- Backpacks mod for Glitchtest game +-- Copyright 2018 James Stevenson +-- GNU GPL version 3 and above + + +local backpacks = {} + +backpacks.form = "size[8,7.5]" .. + jas0.exit_button() .. + "list[current_name;main;0,0.7;8,2]" .. + "field[0.3,3;7,1;rename;;${infotext}]" .. + "button_exit[7,2.67;1,1;ok;OK]" .. + "list[current_player;main;0,3.65;8,1]" .. + "list[current_player;main;0,4.75;8,3;8]" .. + "listring[current_name;main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 3.65) .. +"" + +backpacks.on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Backpack") + meta:set_string("formspec", backpacks.form) + local inv = meta:get_inventory() + inv:set_size("main", 8 * 2) +end + +backpacks.after_place_node = function(pos, placer, itemstack, pointed_thing) + local n_meta = minetest.get_meta(pos) + local i_meta = itemstack:get_meta() + local description = i_meta:get_string("description") + local infotext = description + if infotext == "" then + infotext = itemstack:get_definition().description + end + n_meta:set_string("description", description) + n_meta:set_string("infotext", infotext) + local inv = n_meta:get_inventory() + if i_meta:get_string("inventory") ~= "" then + inv:set_list("main", minetest.deserialize(i_meta:get_string("inventory"))) + end + itemstack:take_item() +end + +backpacks.on_dig = function(pos, node, digger) + if minetest.is_protected(pos, digger:get_player_name()) then + return false + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local list = {} + for i, stack in ipairs(inv:get_list("main")) do + if stack:get_name() == "" then + list[i] = "" + else + list[i] = stack:to_string() + end + end + local fields = {fields = { + description = meta:get_string("description"), + infotext = meta:get_string("description"), + formspec = backpacks.form + }} + local new_list_as_string = minetest.serialize(list) + local new = ItemStack(node) + new:get_meta():from_table(fields) + new:get_meta():set_string("inventory", new_list_as_string) + minetest.remove_node(pos) + local player_inv = digger:get_inventory() + if player_inv:room_for_item("main", new) then + player_inv:add_item("main", new) + else + minetest.add_item(pos, new) + end +end + +backpacks.allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if not string.match(stack:get_name(), "backpacks:backpack_") then + return stack:get_count() + else + return 0 + end +end + +backpacks.preserve_metadata = function(pos, oldnode, oldmeta, drops) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local list = {} + for i, stack in ipairs(inv:get_list("main")) do + if stack:get_name() == "" then + list[i] = "" + else + list[i] = stack:to_string() + end + end + local fields = {fields = { + description = meta:get_string("description"), + infotext = meta:get_string("description"), + formspec = backpacks.form, + }} + local new_list_as_string = minetest.serialize(list) + local new = ItemStack(oldnode) + new:get_meta():from_table(fields) + new:get_meta():set_string("inventory", new_list_as_string) + if drops and drops[1] then + drops[1] = new + end +end + +backpacks.on_receive_fields = function(pos, formname, fields, sender) + if formname ~= "" then + return + end + if fields.rename or + (fields.key_enter and + fields.key_enter_field == "rename") then + local new_name = minetest.formspec_escape(fields.rename) + local meta = minetest.get_meta(pos) + meta:set_string("description", new_name) + meta:set_string("infotext", new_name) + end +end + +backpacks.on_blast = function() -- TODO throw_contents +end + +local wield_index = {} +local function update_wielded(player, inv) + local p_inv = player:get_inventory() + local wielded = p_inv:get_stack("hand", 1) + local list = inv:get_list("dmain") + for i = 1, #list do + list[i] = list[i]:to_string() + end + wielded:get_meta():set_string("inventory", minetest.serialize(list)) + p_inv:set_stack("hand", 1, wielded) +end + +minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) + local name = player:get_player_name() + if (inventory_info.to_index and inventory_info.to_index == wield_index[name]) or + (inventory_info.from_index and inventory_info.from_index == wield_index[name]) or + (inventory_info.index and inventory_info.index == wield_index[name]) then + return 0 + --else + --return inventory_info.count or inventory_info.stack:get_count() + + end +end) + +--minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info) +--end) + +backpacks.d_inv = { + --[[ + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return count + end, + --]] + allow_put = function(inv, listname, index, stack, player) + if stack:get_name():match("backpacks:backpack_") then + return 0 + end + return stack:get_count() + end, + --[[ + allow_take = function(inv, listname, index, stack, player) + return stack:get_count() + end, + --]] + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + update_wielded(player, inv) + end, + on_put = function(inv, listname, index, stack, player) + update_wielded(player, inv) + end, + on_take = function(inv, listname, index, stack, player) + update_wielded(player, inv) + end, +} +backpacks.on_use = function(itemstack, user, pointed_thing) + if not user then + return + end + local name = user:get_player_name() + wield_index[name] = user:get_wield_index() + local d_inv = minetest.get_inventory({type = "detached", + name = "backpack_" .. name}) + if not d_inv then + d_inv = minetest.create_detached_inventory("backpack_" + .. name, backpacks.d_inv) + d_inv:set_size("dmain", 8 * 2) + end + local meta = itemstack:get_meta() + local list = minetest.deserialize(meta:get_string("inventory")) or {} + d_inv:set_list("dmain", list) + local formspec = "size[8,7.5]" .. + jas0.exit_button() .. + "list[detached:backpack_" .. name .. ";dmain;0,0.7;8,2]" .. + "field[0.3,3;7,1;rename;;" .. (meta:get("description") or + itemstack:get_definition().description) .. "]" .. + "button_exit[7,2.67;1,1;ok;OK]" .. + "list[current_player;main;0,3.65;8,1]" .. + "list[current_player;main;0,4.75;8,3;8]" .. + "listring[detached:backpack_" .. name .. ";dmain]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 3.65) .. + "" + minetest.show_formspec(name, "backpacks:backpack", formspec) + local h = user:get_inventory() + h:set_size("hand", 1) + h:set_stack("hand", 1, itemstack) + local faux = ItemStack(itemstack:get_name()) + faux:get_meta():set_string("description", meta:get("description") or + itemstack:get_definition().description) + return faux +end + +minetest.register_on_leaveplayer(function(player) + if not player then + return + end + minetest.remove_detached_inventory("backpack_" .. player:get_player_name()) +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "backpacks:backpack" then + return + end + if fields.rename or + (fields.key_enter and + fields.key_enter_field == "rename") then + local new_name = minetest.formspec_escape(fields.rename) + local wielded = player:get_inventory():get_stack("hand", 1) + local meta = wielded:get_meta() + meta:set_string("description", new_name) + meta:set_string("infotext", new_name) + player:get_inventory():set_stack("hand", 1, wielded) + end + if fields.quit then + player:set_wielded_item(player:get_inventory():get_stack("hand", 1)) + if player:get_meta():get_string("class") == "mage" then + player:get_inventory():set_stack("hand", 1, "jas0:mage") + else + player:get_inventory():set_list("hand", {}) + end + wield_index[player:get_player_name()] = nil + end +end) + +minetest.register_alias("backpacks:backpack", "backpacks:backpack_wool_white") + +-- Colored Wool Backpacks +for k, v in ipairs(dye.dyes) do + minetest.register_node("backpacks:backpack_wool_" .. v[1], { + description = v[2] .. " Wool Backpack", + tiles = { + "wool_" .. v[1] .. ".png^backpacks_backpack_topbottom.png", -- Top + "wool_" .. v[1] .. ".png^backpacks_backpack_topbottom.png", -- Bottom + "wool_" .. v[1] .. ".png^backpacks_backpack_sides.png", -- Right Side + "wool_" .. v[1] .. ".png^backpacks_backpack_sides.png", -- Left Side + "wool_" .. v[1] .. ".png^backpacks_backpack_back.png", -- Back + "wool_" .. v[1] .. ".png^backpacks_backpack_front.png" -- Front + }, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + {-0.4375, -0.5, -0.375, 0.4375, 0.5, 0.375}, + {0.125, -0.375, 0.4375, 0.375, 0.3125, 0.5}, + {-0.375, -0.375, 0.4375, -0.125, 0.3125, 0.5}, + {0.125, 0.1875, 0.375, 0.375, 0.375, 0.4375}, + {-0.375, 0.1875, 0.375, -0.125, 0.375, 0.4375}, + {0.125, -0.375, 0.375, 0.375, -0.25, 0.4375}, + {-0.375, -0.375, 0.375, -0.125, -0.25, 0.4375}, + {-0.3125, -0.375, -0.4375, 0.3125, 0.1875, -0.375}, + {-0.25, -0.3125, -0.5, 0.25, 0.125, -0.4375}, + } + }, + groups = {dig_immediate = 3, oddly_diggable_by_hand = 3, attached_node = 1}, + stack_max = 1, + on_construct = backpacks.on_construct, + after_place_node = backpacks.after_place_node, + on_dig = backpacks.on_dig, + allow_metadata_inventory_put = backpacks.allow_metadata_inventory_put, + preserve_metadata = backpacks.preserve_metadata, + on_receive_fields = backpacks.on_receive_fields, + on_use = backpacks.on_use, + on_bast = backpacks.on_blast, + }) + minetest.register_craft({ + output = "backpacks:backpack_wool_" .. v[1], + recipe = { + {"wool:" .. v[1], "wool:" .. v[1], "wool:" .. v[1]}, + {"wool:" .. v[1], "", "wool:" .. v[1]}, + {"wool:" .. v[1], "wool:" .. v[1], "wool:" .. v[1]}, + } + }) + minetest.register_craft({ + output = "wool:" .. v[1], + type = "shapeless", + recipe = {"backpacks:backpack_wool_" .. v[1]}, + }) +end + +-- Leather backpack +minetest.register_node("backpacks:backpack_leather", { + description = "Leather Backpack", + tiles = { + "backpacks_leather.png^backpacks_backpack_topbottom.png", -- Top + "backpacks_leather.png^backpacks_backpack_topbottom.png", -- Bottom + "backpacks_leather.png^backpacks_backpack_sides.png", -- Right Side + "backpacks_leather.png^backpacks_backpack_sides.png", -- Left Side + "backpacks_leather.png^backpacks_backpack_back.png", -- Back + "backpacks_leather.png^backpacks_backpack_front.png" -- Front + }, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + node_box = { + type = "fixed", + fixed = { + {-0.4375, -0.5, -0.375, 0.4375, 0.5, 0.375}, + {0.125, -0.375, 0.4375, 0.375, 0.3125, 0.5}, + {-0.375, -0.375, 0.4375, -0.125, 0.3125, 0.5}, + {0.125, 0.1875, 0.375, 0.375, 0.375, 0.4375}, + {-0.375, 0.1875, 0.375, -0.125, 0.375, 0.4375}, + {0.125, -0.375, 0.375, 0.375, -0.25, 0.4375}, + {-0.375, -0.375, 0.375, -0.125, -0.25, 0.4375}, + {-0.3125, -0.375, -0.4375, 0.3125, 0.1875, -0.375}, + {-0.25, -0.3125, -0.5, 0.25, 0.125, -0.4375}, + } + }, + groups = {dig_immediate = 3, oddly_diggable_by_hand = 3, attached_node = 1}, + stack_max = 1, + on_construct = backpacks.on_construct, + after_place_node = backpacks.after_place_node, + on_dig = backpacks.on_dig, + allow_metadata_inventory_put = backpacks.allow_metadata_inventory_put, + preserve_metadata = backpacks.preserve_metadata, + on_receive_fields = backpacks.on_receive_fields, + on_use = backpacks.on_use, + on_bast = backpacks.on_blast, +}) + +minetest.register_craft({ + output = "backpacks:backpack_leather", + recipe = { + {"mobs:leather", "mobs:leather", "mobs:leather"}, + {"mobs:leather", "", "mobs:leather"}, + {"mobs:leather", "mobs:leather", "mobs:leather"}, + } +}) +minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + if not player then + return + end + local pos = player:get_pos() + for i = 1, player:get_inventory():get_size("craft") do + if old_craft_grid[i]:get_name():match("backpacks:backpack_") then + local contents = minetest.deserialize(old_craft_grid[i]:get_meta():get("inventory")) + if not contents then + return + end + for i = 1, 16 do + local it = contents[i] + if it ~= "" then + local o = minetest.add_item(pos, it) + if o then + -- from tnt + o:set_acceleration({ + x = 0, + y = -10, + z = 0, + }) + o:set_velocity({ + x = math.random(-3, 3), + y = math.random(0, 10), + z = math.random(-3, 3), + }) + end + end + end + return + end + end +end) diff --git a/mods/backpacks/textures/backpacks_backpack_back.png b/mods/backpacks/textures/backpacks_backpack_back.png new file mode 100644 index 0000000..fd3f5df Binary files /dev/null and b/mods/backpacks/textures/backpacks_backpack_back.png differ diff --git a/mods/backpacks/textures/backpacks_backpack_front.png b/mods/backpacks/textures/backpacks_backpack_front.png new file mode 100644 index 0000000..aec97c7 Binary files /dev/null and b/mods/backpacks/textures/backpacks_backpack_front.png differ diff --git a/mods/backpacks/textures/backpacks_backpack_sides.png b/mods/backpacks/textures/backpacks_backpack_sides.png new file mode 100644 index 0000000..1e635e5 Binary files /dev/null and b/mods/backpacks/textures/backpacks_backpack_sides.png differ diff --git a/mods/backpacks/textures/backpacks_backpack_topbottom.png b/mods/backpacks/textures/backpacks_backpack_topbottom.png new file mode 100644 index 0000000..dce1b1d Binary files /dev/null and b/mods/backpacks/textures/backpacks_backpack_topbottom.png differ diff --git a/mods/backpacks/textures/backpacks_leather.png b/mods/backpacks/textures/backpacks_leather.png new file mode 100644 index 0000000..5d3a27b Binary files /dev/null and b/mods/backpacks/textures/backpacks_leather.png differ diff --git a/mods/beds/README.txt b/mods/beds/README.txt new file mode 100644 index 0000000..b4cf0c4 --- /dev/null +++ b/mods/beds/README.txt @@ -0,0 +1,30 @@ +Minetest Game mod: beds +======================= +See license.txt for license information. + +Authors of source code +---------------------- +Originally by BlockMen (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +BlockMen (CC BY-SA 3.0) + All textures unless otherwise noted + +TumeniNodes (CC BY-SA 3.0) + beds_bed_under.png + +This mod adds a bed to Minetest which allows to skip the night. +To sleep, rightclick the bed. If playing in singleplayer mode the night gets skipped +immediately. If playing multiplayer you get shown how many other players are in bed too, +if all players are sleeping the night gets skipped. The night skip can be forced if more +than 50% of the players are lying in bed and use this option. + +Another feature is a controlled respawning. If you have slept in bed (not just lying in +it) your respawn point is set to the beds location and you will respawn there after +death. +You can disable the respawn at beds by setting "enable_bed_respawn = false" in +minetest.conf. +You can disable the night skip feature by setting "enable_bed_night_skip = false" in +minetest.conf or by using the /set command in-game. diff --git a/mods/beds/api.lua b/mods/beds/api.lua new file mode 100644 index 0000000..ba5bd39 --- /dev/null +++ b/mods/beds/api.lua @@ -0,0 +1,228 @@ + +local reverse = true + +local function destruct_bed(pos, n) + local node = minetest.get_node(pos) + local other + + if n == 2 then + local dir = minetest.facedir_to_dir(node.param2) + other = vector.subtract(pos, dir) + elseif n == 1 then + local dir = minetest.facedir_to_dir(node.param2) + other = vector.add(pos, dir) + end + + if reverse then + reverse = not reverse + minetest.remove_node(other) + minetest.check_for_falling(other) + else + reverse = not reverse + end +end + +function beds.register_bed(name, def) + minetest.register_node(name .. "_bottom", { + description = def.description, + inventory_image = def.inventory_image, + wield_image = def.wield_image, + drawtype = "nodebox", + tiles = def.tiles.bottom, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + stack_max = 1, + groups = { + choppy = 2, + oddly_breakable_by_hand = 2, + flammable = 3, + bed = 1, + fall_damage_add_percent = -80, + bouncy = 101 + }, + sounds = {footstep = {name = "xdecor_bouncy", gain = 0.8}}, + node_box = { + type = "fixed", + fixed = def.nodebox.bottom, + }, + selection_box = { + type = "fixed", + fixed = def.selectionbox, + }, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Bed") + meta:set_string("owner", "") + meta:set_int("public", -1) + end, + 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:is_player() and + placer:get_player_control().sneak) then + return udef.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + + local pos + if udef and udef.buildable_to then + pos = under + else + pos = pointed_thing.above + end + + local player_name = placer and placer:get_player_name() or "" + + if minetest.is_protected(pos, player_name) and + not minetest.check_player_privs(player_name, "protection_bypass") then + minetest.record_protection_violation(pos, player_name) + return itemstack + end + + local node_def = minetest.registered_nodes[minetest.get_node(pos).name] + if not node_def or not node_def.buildable_to then + return itemstack + end + + local dir = placer and placer:get_look_dir() and + minetest.dir_to_facedir(placer:get_look_dir()) or 0 + local botpos = vector.add(pos, minetest.facedir_to_dir(dir)) + + if minetest.is_protected(botpos, player_name) and + not minetest.check_player_privs(player_name, "protection_bypass") then + minetest.record_protection_violation(botpos, player_name) + return itemstack + end + + local botdef = minetest.registered_nodes[minetest.get_node(botpos).name] + if not botdef or not botdef.buildable_to then + return itemstack + end + + minetest.set_node(pos, {name = name .. "_bottom", param2 = dir}) + minetest.set_node(botpos, {name = name .. "_top", param2 = dir}) + local meta = minetest.get_meta(pos) + meta:set_string("owner", player_name) + meta:set_string("infotext", player_name .. "'s Bed") + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + return itemstack + end, + on_destruct = function(pos) + destruct_bed(pos, 1) + end, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not clicker then + return + end + local meta = minetest.get_meta(pos) + local public = meta:get_int("public") + local name = clicker:get_player_name() + if public == -1 and minetest.is_protected(pos, name) then + return + end + beds.selected[name] = pos + local home_name = minetest.get_meta(pos):get_string("home_name") + if home_name == "" then + home_name = "Set home name!" + end + local fs = "size[8,8.5;]" .. + jas0.exit_button() .. + "button_exit[0,-0.167;2,1;sethome;Set Home]" .. + "button_exit[2,-0.167;2,1;setspawn;Set Spawn]" .. + "button_exit[4,-0.167;2,1;sleep;Sleep]" .. + "checkbox[6,-0.13;public;Public;" .. + tostring(public == 1) .."]" .. + "button_exit[7,3.767;1,1;list;List]" .. + "button_exit[6,3.767;1,1;ok;OK]" .. + "field[0.29,4.14;6,0.89;home_name;;" .. + home_name .. "]" .. + "list[current_player;bed;0,0.8;8,4;]" .. + "list[current_player;main;0,4.75;8,4;]" .. + "listring[]" .. + "" + minetest.after(0, minetest.show_formspec, + name, "beds:inventory", fs) + return itemstack + end, + on_rotate = function(pos, node, user, mode, new_param2) + local dir = minetest.facedir_to_dir(node.param2) + local p = vector.add(pos, dir) + local node2 = minetest.get_node_or_nil(p) + if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or + not node.param2 == node2.param2 then + return false + end + if minetest.is_protected(p, user:get_player_name()) then + minetest.record_protection_violation(p, user:get_player_name()) + return false + end + if mode ~= screwdriver.ROTATE_FACE then + return false + end + local newp = vector.add(pos, minetest.facedir_to_dir(new_param2)) + local node3 = minetest.get_node_or_nil(newp) + local node_def = node3 and minetest.registered_nodes[node3.name] + if not node_def or not node_def.buildable_to then + return false + end + if minetest.is_protected(newp, user:get_player_name()) then + minetest.record_protection_violation(newp, user:get_player_name()) + return false + end + node.param2 = new_param2 + -- do not remove_node here - it will trigger destroy_bed() + minetest.set_node(p, {name = "air"}) + minetest.set_node(pos, node) + minetest.set_node(newp, {name = name .. "_top", param2 = new_param2}) + return true + end, + can_dig = function(pos, player) + return beds.can_dig(pos) + end, + }) + + minetest.register_node(name .. "_top", { + drawtype = "nodebox", + tiles = def.tiles.top, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + pointable = false, + groups = { + choppy = 2, + oddly_breakable_by_hand = 2, + flammable = 3, + bed = 2, + fall_damage_add_percent = -80, + bouncy = 101 + }, + sounds = {footstep = {name = "xdecor_bouncy", gain = 0.8}}, + drop = name .. "_bottom", + node_box = { + type = "fixed", + fixed = def.nodebox.top, + }, + on_destruct = function(pos) + destruct_bed(pos, 2) + end, + can_dig = function(pos, player) + local node = minetest.get_node(pos) + local dir = minetest.facedir_to_dir(node.param2) + local p = vector.add(pos, dir) + return beds.can_dig(p) + end, + }) + + minetest.register_alias(name, name .. "_bottom") + + minetest.register_craft({ + output = name, + recipe = def.recipe + }) +end diff --git a/mods/beds/beds.lua b/mods/beds/beds.lua new file mode 100644 index 0000000..b0fa015 --- /dev/null +++ b/mods/beds/beds.lua @@ -0,0 +1,110 @@ +-- Fancy shaped bed +--[[ +beds.register_bed("beds:fancy_bed", { + description = "Fancy Bed", + inventory_image = "beds_bed_fancy.png", + wield_image = "beds_bed_fancy.png", + tiles = { + bottom = { + "beds_bed_top1.png", + "beds_bed_under.png", + "beds_bed_side1.png", + "beds_bed_side1.png^[transformFX", + "beds_bed_foot.png", + "beds_bed_foot.png", + }, + top = { + "beds_bed_top2.png", + "beds_bed_under.png", + "beds_bed_side2.png", + "beds_bed_side2.png^[transformFX", + "beds_bed_head.png", + "beds_bed_head.png", + } + }, + nodebox = { + bottom = { + {-0.5, -0.5, -0.5, -0.375, -0.065, -0.4375}, + {0.375, -0.5, -0.5, 0.5, -0.065, -0.4375}, + {-0.5, -0.375, -0.5, 0.5, -0.125, -0.4375}, + {-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5}, + {0.4375, -0.375, -0.5, 0.5, -0.125, 0.5}, + {-0.4375, -0.3125, -0.4375, 0.4375, -0.0625, 0.5}, + }, + top = { + {-0.5, -0.5, 0.4375, -0.375, 0.1875, 0.5}, + {0.375, -0.5, 0.4375, 0.5, 0.1875, 0.5}, + {-0.5, 0, 0.4375, 0.5, 0.125, 0.5}, + {-0.5, -0.375, 0.4375, 0.5, -0.125, 0.5}, + {-0.5, -0.375, -0.5, -0.4375, -0.125, 0.5}, + {0.4375, -0.375, -0.5, 0.5, -0.125, 0.5}, + {-0.4375, -0.3125, -0.5, 0.4375, -0.0625, 0.4375}, + } + }, + selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5}, + recipe = { + {"", "", "group:stick"}, + {"wool:red", "wool:red", "wool:white"}, + {"group:wood", "group:wood", "group:wood"}, + }, +}) +--]] +minetest.register_alias("beds:bed", "beds:bed_red") +for k, v in ipairs(dye.dyes) do + beds.register_bed("beds:bed_" .. v[1], { + description = v[2] .. " Bed", + inventory_image = "beds_bed.png^(wool_" .. v[1] .. ".png^[mask:beds_blanket.png)", + wield_image = "beds_bed.png^(wool_" .. v[1] .. ".png^[mask:beds_blanket.png)", + tiles = { + bottom = { + "wool_" .. v[1] .. ".png^[transformR90", + "default_wood.png", + "[combine:16x16:0,0=wool_" .. v[1] .. + [[.png:0,11=default_wood.png\^[transformR180]], + "([combine:16x16:0,0=wool_" .. v[1] .. + [[.png:0,11=default_wood.png\^[transformR180)^[transformFX]], + "[combine:16x16", + "[combine:16x16:0,7=wool_" .. v[1] .. + [[.png:0,11=default_wood.png\^[transformR180]], + }, + top = { + "(wool_" .. v[1] .. + [[.png^[combine:16x16:8,0=beds_bed_top_top.png\^[transformR180)^[transformR90]], + "default_wood.png", + "(beds_bed_side_top_r.png^[combine:8x4:-8,0=wool_" .. + v[1] .. [[.png)^[lowpart:27:default_wood.png\^[transformFX]], + "((beds_bed_side_top_r.png^[combine:8x4:-8,0=wool_" .. + v[1] .. [[.png)^[lowpart:27:default_wood.png\^[transformFX)^[transformFX]], + "beds_bed_side_top.png^[lowpart:27:default_wood.png", + "[combine:16x16", + } + }, + nodebox = { + bottom = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + top = {-0.5, -0.5, -0.5, 0.5, 0.06, 0.5}, + }, + selectionbox = {-0.5, -0.5, -0.5, 0.5, 0.06, 1.5}, + recipe = { + {"wool:" .. v[1], "wool:" .. v[1], "wool:white"}, + {"group:wood", "group:wood", "group:wood"} + }, + }) +end +-- Aliases for PilzAdam's beds mod + +minetest.register_alias("beds:bed_bottom", "beds:bed_red_bottom") +minetest.register_alias("beds:bed_top", "beds:bed_red_top") + +-- Fuel +--[[ +minetest.register_craft({ + type = "fuel", + recipe = "beds:fancy_bed_bottom", + burntime = 13, +}) +--]] +minetest.register_craft({ + type = "fuel", + recipe = "beds:bed_bottom", + burntime = 12, +}) diff --git a/mods/beds/depends.txt b/mods/beds/depends.txt new file mode 100644 index 0000000..d03270d --- /dev/null +++ b/mods/beds/depends.txt @@ -0,0 +1,4 @@ +default +wool +jas0 +dye diff --git a/mods/beds/functions.lua b/mods/beds/functions.lua new file mode 100644 index 0000000..3e7a0a0 --- /dev/null +++ b/mods/beds/functions.lua @@ -0,0 +1,447 @@ +local pi = math.pi +local player_in_bed = 0 +local is_sp = minetest.is_singleplayer() +local enable_respawn = minetest.settings:get_bool("enable_bed_respawn") +if enable_respawn == nil then + enable_respawn = true +end + +-- Helper functions + +local function get_look_yaw(pos) + local rotation = minetest.get_node(pos).param2 + if rotation > 3 then + rotation = rotation % 4 -- Mask colorfacedir values + end + if rotation == 1 then + return pi / 2, rotation + elseif rotation == 3 then + return -pi / 2, rotation + elseif rotation == 0 then + return pi, rotation + else + return 0, rotation + end +end + +local function is_night_skip_enabled() + local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip") + if enable_night_skip == nil then + enable_night_skip = true + end + return enable_night_skip +end + +local function check_in_beds(players) + local in_bed = beds.player + if not players then + players = minetest.get_connected_players() + end + + for n, player in ipairs(players) do + local name = player:get_player_name() + if not in_bed[name] then + return false + end + end + + return #players > 0 +end + +local function lay_down(player, pos, bed_pos, state, skip) + local name = player:get_player_name() + local hud_flags = player:hud_get_flags() + + if not player or not name then + return + end + + -- stand up + if state ~= nil and not state then + local p = beds.pos[name] or nil + if beds.player[name] ~= nil then + beds.player[name] = nil + beds.bed_position[name] = nil + player_in_bed = player_in_bed - 1 + end + -- skip here to prevent sending player specific changes (used for leaving players) + if skip then + return + end + if p then + player:set_pos(p) + end + + -- physics, eye_offset, etc + player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + player:set_look_horizontal(math.random(1, 180) / 100) + default.player_attached[name] = false + player:set_physics_override(1, 1, 1) + hud_flags.wielditem = true + default.player_set_animation(player, "stand" , 30) + + -- lay down + else + beds.player[name] = 1 + beds.pos[name] = pos + beds.bed_position[name] = bed_pos + player_in_bed = player_in_bed + 1 + + -- physics, eye_offset, etc + player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0}) + local yaw, param2 = get_look_yaw(bed_pos) + player:set_look_horizontal(yaw) + local dir = minetest.facedir_to_dir(param2) + local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2} + player:set_physics_override(0, 0, 0) + player:set_pos(p) + default.player_attached[name] = true + hud_flags.wielditem = false + default.player_set_animation(player, "lay" , 0) + end + + player:hud_set_flags(hud_flags) +end + +local function update_formspecs(finished) + local ges = #minetest.get_connected_players() + local form_n + local is_majority = (ges / 2) < player_in_bed + + if finished then + form_n = beds.formspec .. "label[2.7,11; Good morning.]" + else + form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) .. + " of " .. tostring(ges) .. " players are in bed]" + if is_majority and is_night_skip_enabled() then + form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night/day skip]" + end + end + + for name,_ in pairs(beds.player) do + minetest.show_formspec(name, "beds_form", form_n) + end +end + + +-- Public functions + +function beds.kick_players() + for name, _ in pairs(beds.player) do + local player = minetest.get_player_by_name(name) + lay_down(player, nil, nil, false) + end +end + +function beds.skip_night(f) + if f then + return + end + if beds.night_toggle then + minetest.set_timeofday((beds.time.hour * 60 + beds.time.min) / 1440) + beds.night_toggle = false + else + minetest.set_timeofday(((beds.time.hour + 12) % 24 * 60 + beds.time.min) / 1440) + beds.night_toggle = true + end +end + +function beds.on_rightclick(pos, player) + local name = player:get_player_name() + local ppos = player:get_pos() + local tod = minetest.get_timeofday() + + -- move to bed + if not beds.player[name] then + lay_down(player, ppos, pos) + beds.set_spawns() -- save respawn positions when entering bed + else + lay_down(player, nil, nil, false) + end + + if not is_sp then + update_formspecs(false) + end + + -- skip the night and let all players stand up + if check_in_beds() then + minetest.after(2, function() + if not is_sp then + update_formspecs(is_night_skip_enabled()) + end + if is_night_skip_enabled() then + beds.skip_night() + beds.kick_players() + end + end) + end +end + +function beds.can_dig(bed_pos) + -- Check all players in bed which one is at the expected position + for _, player_bed_pos in pairs(beds.bed_position) do + if vector.equals(bed_pos, player_bed_pos) then + return false + end + end + return true +end + +-- Callbacks +-- Only register respawn callback if respawn enabled +if enable_respawn then + -- respawn player at bed if enabled and valid position is found + minetest.register_on_respawnplayer(function(player) + local name = player:get_player_name() + local pos = beds.spawn[name] + if pos then + player:set_pos(pos) + return true + end + end) +end + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + lay_down(player, nil, nil, false, true) + beds.player[name] = nil + if check_in_beds() then + minetest.after(2, function() + update_formspecs(is_night_skip_enabled()) + if is_night_skip_enabled() then + beds.skip_night() + beds.kick_players() + end + end) + end +end) + +beds.gdi = {} +local function beds_list_fs(player, index, tab) + if not player then + return + end + index = index or 1 + tab = tonumber(tab) or 1 + local name = player:get_player_name() + beds.gdi[name] = {} + local beds_list_string = "" + if tab == 1 and not beds.beds[name] then + return jas0.message(name, "You do not have any beds saved.") + end + local formspec = "size[6,4.75]" .. + --"box[-0.9,-1.1;6.67,0.5;black]" .. + "tabheader[0,0;tab;Private,Public;" .. tostring(tab) .. + ";false;true]" .. + "button_exit[4,4.25;2,1;warp;Warp]" .. + "" + if tab == 1 then + formspec = formspec .. + "button[0,4.25;2,1;delete;Delete]" .. + "" + for warp_name, destination in pairs(beds.beds[name]) do + beds_list_string = beds_list_string .. "," .. warp_name + beds.gdi[name][#beds.gdi[name] + 1] = warp_name + end + else + formspec = formspec .. + "button[0,4.25;2,1;show;Show]" .. + "tablecolumns[color;tree;text]" .. + "" + for player_name, destination in pairs(beds.beds_public) do + beds_list_string = beds_list_string .. "," .. + "#FFF,0," .. player_name .. "," .. + "" + beds.gdi[name][#beds.gdi[name] + 1] = {name = player_name} + for dest_name, _ in pairs(destination) do + beds_list_string = beds_list_string .. + "#FFF,1," .. dest_name .. "," .. + "" + beds.gdi[name][#beds.gdi[name] + 1] = {name = player_name, dest = dest_name} + end + beds_list_string = beds_list_string:sub(1, -2) + end + end + formspec = formspec .. "table[-0.1,-0.1;6,4.34;beds_list_item;" .. + beds_list_string:sub(2, -1) .. ";" .. index .. "]" .. + "" + return formspec +end + +local beds_list_index = {} +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "beds:inventory" then + if not player then + return + end + local pos = player:get_pos() + local name = player:get_player_name() + local bed_pos = beds.selected[name] + local meta = minetest.get_meta(bed_pos) + if fields.sethome then + walkie.players[name].waypoints.saved = pos + walkie.players[name].waypoints.pos = pos + player:hud_change(walkie.meters[name].waypoint, + "world_pos", pos) + player:get_meta():set_string("waypoints", + minetest.serialize(walkie.players[name].waypoints)) + minetest.chat_send_player(name, "Saved home position!") + elseif fields.setspawn then + beds.spawn[name] = pos + minetest.chat_send_player(name, "Saved spawn position!") + elseif fields.sleep then + return beds.on_rightclick(bed_pos, player) + elseif fields.public then + local owner = meta:get_string("owner") + if minetest.is_protected(bed_pos, name) or + owner ~= name then + jas0.message(name, + "This bed is protected. " .. + "Its state cannot be changed.", true) + return + end + if owner == "" then + meta:set_string("owner", name) + end + meta:set_int("public", -meta:get_int("public")) + elseif fields.list then + local tab = 2 + if beds.beds[name] then + tab = 1 + end + return minetest.after(0.1, minetest.show_formspec, name, + "beds:list", beds_list_fs(player, 1, tab)) + elseif fields.home_name then + if fields.home_name == "Set home name!" or + not fields.ok and + not (fields.key_enter and + fields.key_enter_field == "home_name") then + return + end + if name ~= meta:get_string("owner") then + return jas0.message(name, + "You are not the owner of this bed!", + true) + end + local home_name = fields.home_name + home_name = minetest.formspec_escape(home_name):gsub("%W", "") + if not beds.beds[name] then + beds.beds[name] = {} + end + if beds.beds[name][home_name] or beds.beds_public[name][home_name] then + return jas0.message(name, "This name already exists!", + true) + end + if not bed_pos then + return + end + local old_home_name = meta:get_string("home_name") + if old_home_name ~= "" then + if beds.beds[name][old_home_name] then + beds.beds[name][old_home_name] = nil + end + if beds.beds_public[name][old_home_name] then + beds.beds_public[name][old_home_name] = nil + end + end + + meta:set_string("home_name", home_name) + beds.beds[name][home_name] = pos + if meta:get_int("public") == 1 then + if not beds.beds_public[name] then + beds.beds_public[name] = {} + end + beds.beds_public[name][home_name] = pos + end + return jas0.message(name, "Saved " .. home_name, true) + end + elseif formname == "beds:list" then + local name = player:get_player_name() + if fields.tab then + return minetest.after(0.1, minetest.show_formspec, name, + "beds:list", + beds_list_fs(player, 1, fields.tab)) + end + if not beds_list_index[name] then + beds_list_index[name] = 1 + end + if fields.beds_list_item then + local item = fields.beds_list_item + local exploded = minetest.explode_table_event(item) + if exploded.type == "CHG" then + beds_list_index[name] = exploded.row + end + end + if fields.delete then + local index = beds_list_index[name] + local warp_name = beds.gdi[name][index] + if warp_name then + return jas0.message(name, + "Are you certain you wish to " .. + "delete " .. warp_name .. "?", true, + "beds:list_delete") + end + end + if fields.warp then + local index = beds_list_index[name] + local owner_name + if beds.gdi[name][index] then + owner_name = beds.gdi[name][index]["name"] + end + local warp_name + if owner_name then + warp_name = beds.gdi[name][index]["dest"] + else + warp_name = beds.gdi[name][index] + end + local pos + if owner_name then + pos = beds.beds_public[owner_name][warp_name] + else + pos = beds.beds[name][warp_name] + end + if pos then + jas0.message(name, "Warped to " .. + warp_name .. ".") + player:set_pos(pos) + end + end + if fields.quit then + beds_list_index[name] = nil + end + elseif formname == "beds:list_delete" and fields.ok then + local name = player:get_player_name() + if not beds_list_index[name] then + beds_list_index[name] = 1 + end + local index = beds_list_index[name] + local warp_name = beds.gdi[name][index] + if warp_name then + jas0.message(name, "Deleted " .. warp_name .. ".") + beds.beds[name][warp_name] = nil + beds.beds_public[name][warp_name] = nil + end + return minetest.after(0.1, minetest.show_formspec, + name, "beds:list", beds_list_fs(player, index)) + elseif formname == "beds_form" then + -- Because "Force night skip" button is a button_exit, + -- it will set fields.quit and lay_down call will change + -- value of player_in_bed, so it must be taken earlier. + local last_player_in_bed = player_in_bed + if fields.quit or fields.leave then + lay_down(player, nil, nil, false) + update_formspecs(false) + end + if fields.force then + local is_majority = (#minetest.get_connected_players() / 2) < last_player_in_bed + if is_majority and is_night_skip_enabled() then + update_formspecs(true) + beds.skip_night(true) + beds.kick_players() + else + update_formspecs(false) + end + end + end + return +end) diff --git a/mods/beds/init.lua b/mods/beds/init.lua new file mode 100644 index 0000000..3d66e51 --- /dev/null +++ b/mods/beds/init.lua @@ -0,0 +1,63 @@ +-- This version of the beds mod is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +beds = {} +beds.player = {} +beds.bed_position = {} +beds.pos = {} +beds.spawn = {} +beds.formspec = "size[8,15;false]" .. + "no_prepend[]" .. + "bgcolor[#080808BB;true]" .. + "button_exit[2,12;4,0.75;leave;Leave Bed]" .. +"" +beds.time = os.date("*t") +minetest.after(1, minetest.set_timeofday, (beds.time.hour * 60 + beds.time.min) / 1440) +beds.night_toggle = false +beds.selected = {} +beds.beds = {} +beds.beds_public = {} +local store = minetest.get_mod_storage() +if store:get_string("beds") ~= "" then + beds.beds = minetest.deserialize(store:get_string("beds")) +end +if store:get_string("beds_public") ~= "" then + beds.beds_public = minetest.deserialize(store:get_string("beds_public")) +end +local modpath = minetest.get_modpath("beds") +local step = 0 + +minetest.register_globalstep(function(dtime) + if step < 60 then + step = step + dtime + return + end + --minetest.log("action", "Setting time.") + beds.time = os.date("*t") + if beds.night_toggle then + minetest.set_timeofday(((beds.time.hour + 12) % 24 * 60 + beds.time.min) / 1440) + else + minetest.set_timeofday((beds.time.hour * 60 + beds.time.min) / 1440) + end + store:set_string("beds", minetest.serialize(beds.beds)) + store:set_string("beds_public", minetest.serialize(beds.beds_public)) + step = 0 +end) + +minetest.register_on_shutdown(function() + store:set_string("beds", minetest.serialize(beds.beds)) + store:set_string("beds_public", minetest.serialize(beds.beds_public)) + +end) +minetest.register_on_joinplayer(function(player) + if not player then + return + end + player:get_inventory():set_size("bed", 8 * 3) +end) + +dofile(modpath .. "/functions.lua") +dofile(modpath .. "/api.lua") +dofile(modpath .. "/beds.lua") +dofile(modpath .. "/spawns.lua") diff --git a/mods/beds/license.txt b/mods/beds/license.txt new file mode 100644 index 0000000..f3c517f --- /dev/null +++ b/mods/beds/license.txt @@ -0,0 +1,61 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2014-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2018 TumeniNodes + +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/beds/spawns.lua b/mods/beds/spawns.lua new file mode 100644 index 0000000..baee364 --- /dev/null +++ b/mods/beds/spawns.lua @@ -0,0 +1,63 @@ +local world_path = minetest.get_worldpath() +local org_file = world_path .. "/beds_spawns" +local file = world_path .. "/beds_spawns" +local bkwd = false + +-- check for PA's beds mod spawns +local cf = io.open(world_path .. "/beds_player_spawns", "r") +if cf ~= nil then + io.close(cf) + file = world_path .. "/beds_player_spawns" + bkwd = true +end + +function beds.read_spawns() + local spawns = beds.spawn + local input = io.open(file, "r") + if input and not bkwd then + repeat + local x = input:read("*n") + if x == nil then + break + end + local y = input:read("*n") + local z = input:read("*n") + local name = input:read("*l") + spawns[name:sub(2)] = {x = x, y = y, z = z} + until input:read(0) == nil + io.close(input) + elseif input and bkwd then + beds.spawn = minetest.deserialize(input:read("*all")) + input:close() + beds.save_spawns() + os.rename(file, file .. ".backup") + file = org_file + end +end + +beds.read_spawns() + +function beds.save_spawns() + if not beds.spawn then + return + end + local data = {} + local output = io.open(org_file, "w") + for k, v in pairs(beds.spawn) do + table.insert(data, string.format("%.1f %.1f %.1f %s\n", v.x, v.y, v.z, k)) + end + output:write(table.concat(data)) + io.close(output) +end + +function beds.set_spawns() + for name,_ in pairs(beds.player) do + local player = minetest.get_player_by_name(name) + local p = player:get_pos() + -- but don't change spawn location if borrowing a bed + if not minetest.is_protected(p, name) then + beds.spawn[name] = p + end + end + beds.save_spawns() +end diff --git a/mods/beds/textures/beds_bed.png b/mods/beds/textures/beds_bed.png new file mode 100644 index 0000000..5c0054c Binary files /dev/null and b/mods/beds/textures/beds_bed.png differ diff --git a/mods/beds/textures/beds_bed_fancy.png b/mods/beds/textures/beds_bed_fancy.png new file mode 100644 index 0000000..4f9e8a7 Binary files /dev/null and b/mods/beds/textures/beds_bed_fancy.png differ diff --git a/mods/beds/textures/beds_bed_foot.png b/mods/beds/textures/beds_bed_foot.png new file mode 100644 index 0000000..74d84c8 Binary files /dev/null and b/mods/beds/textures/beds_bed_foot.png differ diff --git a/mods/beds/textures/beds_bed_head.png b/mods/beds/textures/beds_bed_head.png new file mode 100644 index 0000000..763f5e1 Binary files /dev/null and b/mods/beds/textures/beds_bed_head.png differ diff --git a/mods/beds/textures/beds_bed_side1.png b/mods/beds/textures/beds_bed_side1.png new file mode 100644 index 0000000..1ed8158 Binary files /dev/null and b/mods/beds/textures/beds_bed_side1.png differ diff --git a/mods/beds/textures/beds_bed_side2.png b/mods/beds/textures/beds_bed_side2.png new file mode 100644 index 0000000..9d1384d Binary files /dev/null and b/mods/beds/textures/beds_bed_side2.png differ diff --git a/mods/beds/textures/beds_bed_side_bottom.png b/mods/beds/textures/beds_bed_side_bottom.png new file mode 100644 index 0000000..99ff309 Binary files /dev/null and b/mods/beds/textures/beds_bed_side_bottom.png differ diff --git a/mods/beds/textures/beds_bed_side_bottom_r.png b/mods/beds/textures/beds_bed_side_bottom_r.png new file mode 100644 index 0000000..6f870e8 Binary files /dev/null and b/mods/beds/textures/beds_bed_side_bottom_r.png differ diff --git a/mods/beds/textures/beds_bed_side_top.png b/mods/beds/textures/beds_bed_side_top.png new file mode 100644 index 0000000..b2807c5 Binary files /dev/null and b/mods/beds/textures/beds_bed_side_top.png differ diff --git a/mods/beds/textures/beds_bed_side_top_r.png b/mods/beds/textures/beds_bed_side_top_r.png new file mode 100644 index 0000000..429ad7d Binary files /dev/null and b/mods/beds/textures/beds_bed_side_top_r.png differ diff --git a/mods/beds/textures/beds_bed_top1.png b/mods/beds/textures/beds_bed_top1.png new file mode 100644 index 0000000..b6fcc2c Binary files /dev/null and b/mods/beds/textures/beds_bed_top1.png differ diff --git a/mods/beds/textures/beds_bed_top2.png b/mods/beds/textures/beds_bed_top2.png new file mode 100644 index 0000000..2fe5bf2 Binary files /dev/null and b/mods/beds/textures/beds_bed_top2.png differ diff --git a/mods/beds/textures/beds_bed_top_bottom.png b/mods/beds/textures/beds_bed_top_bottom.png new file mode 100644 index 0000000..9b78be6 Binary files /dev/null and b/mods/beds/textures/beds_bed_top_bottom.png differ diff --git a/mods/beds/textures/beds_bed_top_top.png b/mods/beds/textures/beds_bed_top_top.png new file mode 100644 index 0000000..e877c80 Binary files /dev/null and b/mods/beds/textures/beds_bed_top_top.png differ diff --git a/mods/beds/textures/beds_bed_under.png b/mods/beds/textures/beds_bed_under.png new file mode 100644 index 0000000..a930115 Binary files /dev/null and b/mods/beds/textures/beds_bed_under.png differ diff --git a/mods/beds/textures/beds_blanket.png b/mods/beds/textures/beds_blanket.png new file mode 100644 index 0000000..c745d3b Binary files /dev/null and b/mods/beds/textures/beds_blanket.png differ diff --git a/mods/beds/textures/beds_transparent.png b/mods/beds/textures/beds_transparent.png new file mode 100644 index 0000000..2dc0e3d Binary files /dev/null and b/mods/beds/textures/beds_transparent.png differ diff --git a/mods/boats/README.txt b/mods/boats/README.txt new file mode 100644 index 0000000..a2ccb48 --- /dev/null +++ b/mods/boats/README.txt @@ -0,0 +1,31 @@ +Minetest Game mod: boats +======================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by PilzAdam (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures and model) +------------------------------------- +Textures: Zeg9 (CC BY-SA 3.0) +Model: thetoon and Zeg9 (CC BY-SA 3.0), + modified by PavelS(SokolovPavel) (CC BY-SA 3.0), + modified by sofar (CC BY-SA 3.0) + +Controls +-------- +Right mouse button = Enter or exit boat when pointing at boat. +Forward = Speed up. + Slow down when moving backwards. +Forward + backward = Enable cruise mode: Boat will accelerate to maximum forward + speed and remain at that speed without needing to hold the + forward key. +Backward = Slow down. + Speed up when moving backwards. + Disable cruise mode. +Left = Turn to the left. + Turn to the right when moving backwards. +Right = Turn to the right. + Turn to the left when moving backwards. diff --git a/mods/boats/depends.txt b/mods/boats/depends.txt new file mode 100644 index 0000000..8e482ce --- /dev/null +++ b/mods/boats/depends.txt @@ -0,0 +1,2 @@ +default +player_api diff --git a/mods/boats/init.lua b/mods/boats/init.lua new file mode 100644 index 0000000..00cf791 --- /dev/null +++ b/mods/boats/init.lua @@ -0,0 +1,299 @@ +-- +-- Helper functions +-- + +local function is_water(pos) + local nn = minetest.get_node(pos).name + return minetest.get_item_group(nn, "water") ~= 0 +end + + +local function get_sign(i) + if i == 0 then + return 0 + else + return i / math.abs(i) + end +end + + +local function get_velocity(v, yaw, y) + local x = -math.sin(yaw) * v + local z = math.cos(yaw) * v + return {x = x, y = y, z = z} +end + + +local function get_v(v) + return math.sqrt(v.x ^ 2 + v.z ^ 2) +end + +-- +-- Boat entity +-- + +local boat = { + initial_properties = { + physical = true, + -- Warning: Do not change the position of the collisionbox top surface, + -- lowering it causes the boat to fall through the world if underwater + collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5}, + visual = "mesh", + mesh = "boats_boat.obj", + textures = {"default_wood.png"}, + }, + + driver = nil, + v = 0, + last_v = 0, + removed = false, + auto = false +} + + +function boat.on_rightclick(self, clicker) + if not clicker or not clicker:is_player() then + return + end + local name = clicker:get_player_name() + if self.driver and name == self.driver then + self.driver = nil + self.auto = false + clicker:set_detach() + player_api.player_attached[name] = false + player_api.set_animation(clicker, "stand" , 30) + local pos = clicker:get_pos() + pos = {x = pos.x, y = pos.y + 0.2, z = pos.z} + minetest.after(0.1, function() + clicker:set_pos(pos) + end) + elseif not self.driver then + local attach = clicker:get_attach() + if attach and attach:get_luaentity() then + local luaentity = attach:get_luaentity() + if luaentity.driver then + luaentity.driver = nil + end + clicker:set_detach() + end + self.driver = name + clicker:set_attach(self.object, "", + {x = 0.5, y = 1, z = -3}, {x = 0, y = 0, z = 0}) + player_api.player_attached[name] = true + minetest.after(0.2, function() + player_api.set_animation(clicker, "sit" , 30) + end) + clicker:set_look_horizontal(self.object:get_yaw()) + end +end + + +-- If driver leaves server while driving boat +function boat.on_detach_child(self, child) + self.driver = nil + self.auto = false +end + + +function boat.on_activate(self, staticdata, dtime_s) + self.object:set_armor_groups({immortal = 1}) + if staticdata then + self.v = tonumber(staticdata) + end + self.last_v = self.v +end + + +function boat.get_staticdata(self) + return tostring(self.v) +end + + +function boat.on_punch(self, puncher) + if not puncher or not puncher:is_player() or self.removed then + return + end + + local name = puncher:get_player_name() + if self.driver and name == self.driver then + self.driver = nil + puncher:set_detach() + player_api.player_attached[name] = false + end + if not self.driver then + self.removed = true + local inv = puncher:get_inventory() + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(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 + if not leftover:is_empty() then + minetest.add_item(self.object:get_pos(), leftover) + end + end + -- delay remove to ensure player is detached + minetest.after(0.1, function() + self.object:remove() + end) + end +end + + +function boat.on_step(self, dtime) + self.v = get_v(self.object:get_velocity()) * get_sign(self.v) + if self.driver then + local driver_objref = minetest.get_player_by_name(self.driver) + if driver_objref then + local ctrl = driver_objref:get_player_control() + if ctrl.up and ctrl.down then + if not self.auto then + self.auto = true + minetest.chat_send_player(self.driver, "[boats] Cruise on") + end + elseif ctrl.down then + self.v = self.v - dtime * 1.8 + if self.auto then + self.auto = false + minetest.chat_send_player(self.driver, "[boats] Cruise off") + end + elseif ctrl.up or self.auto then + self.v = self.v + dtime * 1.8 + end + if ctrl.left then + if self.v < -0.001 then + self.object:set_yaw(self.object:get_yaw() - dtime * 0.9) + else + self.object:set_yaw(self.object:get_yaw() + dtime * 0.9) + end + elseif ctrl.right then + if self.v < -0.001 then + self.object:set_yaw(self.object:get_yaw() + dtime * 0.9) + else + self.object:set_yaw(self.object:get_yaw() - dtime * 0.9) + end + end + end + end + local velo = self.object:get_velocity() + if self.v == 0 and velo.x == 0 and velo.y == 0 and velo.z == 0 then + self.object:set_pos(self.object:get_pos()) + return + end + local s = get_sign(self.v) + self.v = self.v - dtime * 0.6 * s + if s ~= get_sign(self.v) then + self.object:set_velocity({x = 0, y = 0, z = 0}) + self.v = 0 + return + end + if math.abs(self.v) > 5 then + self.v = 5 * get_sign(self.v) + end + + local p = self.object:get_pos() + p.y = p.y - 0.5 + local new_velo + local new_acce = {x = 0, y = 0, z = 0} + if not is_water(p) then + local nodedef = minetest.registered_nodes[minetest.get_node(p).name] + if (not nodedef) or nodedef.walkable then + self.v = 0 + new_acce = {x = 0, y = 1, z = 0} + else + new_acce = {x = 0, y = -9.8, z = 0} + end + new_velo = get_velocity(self.v, self.object:get_yaw(), + self.object:get_velocity().y) + self.object:set_pos(self.object:get_pos()) + else + p.y = p.y + 1 + if is_water(p) then + local y = self.object:get_velocity().y + if y >= 5 then + y = 5 + elseif y < 0 then + new_acce = {x = 0, y = 20, z = 0} + else + new_acce = {x = 0, y = 5, z = 0} + end + new_velo = get_velocity(self.v, self.object:get_yaw(), y) + self.object:set_pos(self.object:get_pos()) + else + new_acce = {x = 0, y = 0, z = 0} + if math.abs(self.object:get_velocity().y) < 1 then + local pos = self.object:get_pos() + pos.y = math.floor(pos.y) + 0.5 + self.object:set_pos(pos) + new_velo = get_velocity(self.v, self.object:get_yaw(), 0) + else + new_velo = get_velocity(self.v, self.object:get_yaw(), + self.object:get_velocity().y) + self.object:set_pos(self.object:get_pos()) + end + end + end + self.object:set_velocity(new_velo) + self.object:set_acceleration(new_acce) +end + + +minetest.register_entity("boats:boat", boat) + + +minetest.register_craftitem("boats:boat", { + description = "Boat", + inventory_image = "boats_inventory.png", + wield_image = "boats_wield.png", + wield_scale = {x = 2, y = 2, z = 1}, + liquids_pointable = true, + 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:is_player() 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 + if not is_water(pointed_thing.under) then + return itemstack + end + pointed_thing.under.y = pointed_thing.under.y + 0.5 + boat = minetest.add_entity(pointed_thing.under, "boats:boat") + if boat then + if placer then + boat:set_yaw(placer:get_look_horizontal()) + end + local player_name = placer and placer:get_player_name() or "" + if not (creative and creative.is_enabled_for and + creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + end + return itemstack + end, +}) + + +minetest.register_craft({ + output = "boats:boat", + recipe = { + {"", "", "" }, + {"group:wood", "", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, + }, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "boats:boat", + burntime = 20, +}) diff --git a/mods/boats/license.txt b/mods/boats/license.txt new file mode 100644 index 0000000..d4afe75 --- /dev/null +++ b/mods/boats/license.txt @@ -0,0 +1,63 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures and model) +-------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2012-2016 Zeg9 +Copyright (C) 2012-2016 thetoon +Copyright (C) 2012-2016 PavelS(SokolovPavel) +Copyright (C) 2016 sofar (sofar@foo-projects.org) + +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/boats/models/boats_boat.obj b/mods/boats/models/boats_boat.obj new file mode 100644 index 0000000..0f21e47 --- /dev/null +++ b/mods/boats/models/boats_boat.obj @@ -0,0 +1,358 @@ +# Blender v2.76 (sub 11) OBJ File: 'boat.blend' +# www.blender.org +mtllib boat.mtl +o boats_boat +v -6.786140 -3.033999 -9.415440 +v -6.786140 -1.967150 -9.415440 +v -6.786140 -1.967150 8.793510 +v -6.786140 -3.033999 8.793510 +v 5.732520 -1.967150 -9.415440 +v 5.732520 -3.033999 -9.415440 +v 5.732520 -3.033999 8.793510 +v 5.732520 -1.967150 8.793510 +v -2.233900 -3.033999 -9.415440 +v -2.233900 -1.967150 -9.415440 +v -2.233900 -1.967150 8.793510 +v -2.233900 -3.033999 8.793510 +v 2.318340 -3.033999 -9.415440 +v 2.318340 -1.967150 -9.415440 +v 2.318340 -1.967150 8.793510 +v 2.318340 -3.033999 8.793510 +v -3.371960 -3.033999 8.793510 +v -3.371960 -1.967150 8.793510 +v -3.371960 -1.967150 -9.415440 +v -3.371960 -3.033999 -9.415440 +v 2.318340 0.276645 8.793510 +v 1.180280 -1.967150 8.793510 +v 5.732520 0.276645 8.793510 +v 5.732520 1.039180 8.793510 +v 6.870580 0.276645 8.793510 +v 6.870580 -1.967150 8.793510 +v 2.318340 1.039180 8.793510 +v 1.180280 0.276645 8.793510 +v 1.180280 1.039180 8.793510 +v 1.180280 -3.033999 8.793510 +v -2.233900 0.276645 8.793510 +v -3.371960 0.276645 8.793510 +v -2.233900 1.039180 8.793510 +v -3.371960 1.039180 8.793510 +v -6.786140 0.276645 8.793510 +v -7.786200 0.276645 8.793510 +v -7.786200 -1.967150 8.793510 +v -6.786140 1.039180 8.793510 +v 1.180280 -1.967150 -9.415440 +v 1.180280 -3.033999 -9.415440 +v 2.318340 0.276645 -9.415440 +v 1.180280 0.276645 -9.415440 +v 2.318340 1.039180 -9.415440 +v 5.732520 0.276645 -9.415440 +v 6.870580 -1.967150 -9.415440 +v 5.732520 1.039180 -9.415440 +v 6.870580 0.276645 -9.415440 +v 0.042220 1.039180 -9.415440 +v 1.180280 1.039180 -9.415440 +v 0.042220 -1.967150 -9.415440 +v -1.095840 -1.967150 -9.415440 +v -2.233900 0.276645 -9.415440 +v -3.371960 0.276645 -9.415440 +v -2.233900 1.039180 -9.415440 +v -1.095840 1.039180 -9.415440 +v -3.371960 1.039180 -9.415440 +v -6.786140 0.276645 -9.415440 +v -6.786140 1.039180 -9.415440 +v -7.786200 -1.967150 -9.415440 +v -7.786200 0.276645 -9.415440 +v -1.095840 0.156645 -12.044100 +v -1.095840 -4.601110 -9.415440 +v -1.095840 1.039181 -10.802900 +v -1.095840 2.868579 -10.802900 +v -1.095840 2.868580 -7.883420 +v -1.095840 3.746069 -12.034100 +v -1.095840 3.746070 -7.883420 +v -1.095840 0.156645 -14.294900 +v -1.095840 -4.601110 -14.284900 +v 0.042220 -4.601110 -14.284900 +v 0.042220 -4.601110 -9.415440 +v 0.042220 1.039181 -10.802900 +v 0.042220 0.156645 -12.044100 +v 0.042220 2.868579 -10.802900 +v 0.042220 0.156645 -14.294900 +v 0.042220 3.746069 -12.034100 +v 0.042220 3.746070 -7.883420 +v 0.042220 2.868580 -7.883420 +v -1.096322 -3.033999 -9.415440 +v 0.044046 -3.035397 -9.415440 +vt 1.000000 0.187500 +vt -1.000000 0.312500 +vt 1.000000 0.312500 +vt 0.687500 1.000000 +vt 0.500000 0.875000 +vt 0.500000 0.625000 +vt -1.000000 0.062500 +vt 1.000000 0.062500 +vt 1.000000 -0.000000 +vt -1.000000 0.125000 +vt 1.000000 0.125000 +vt 0.437500 0.125000 +vt 0.312500 0.500000 +vt 0.312500 0.125000 +vt 1.000000 0.625000 +vt -1.000000 0.500000 +vt 1.000000 0.500000 +vt 0.187500 0.687500 +vt -0.187500 0.687500 +vt -0.187500 0.312500 +vt 1.000000 0.812500 +vt -1.000000 0.937500 +vt -1.000000 0.812500 +vt 0.812500 0.687500 +vt 1.187500 0.687500 +vt 0.812500 0.312500 +vt 1.000000 0.562500 +vt 0.312500 0.437500 +vt 1.000000 0.437500 +vt 1.000000 0.750000 +vt -1.000000 0.875000 +vt -1.000000 0.750000 +vt -1.000000 1.000000 +vt 1.000000 1.000000 +vt 0.437500 0.625000 +vt 0.562500 0.437500 +vt 0.562500 0.625000 +vt -1.000000 0.437500 +vt -1.000000 0.000000 +vt 0.500000 0.062500 +vt 0.375000 0.750000 +vt 0.500000 0.750000 +vt -1.000000 0.250000 +vt -1.000000 0.687500 +vt 1.000000 0.687500 +vt 0.625000 0.375000 +vt 1.000000 0.375000 +vt 1.000000 0.250000 +vt 1.000000 0.937500 +vt 0.437500 0.812500 +vt 0.312500 0.312500 +vt 0.312500 0.812500 +vt 0.437500 0.312500 +vt 0.437500 0.437500 +vt 0.687500 0.812500 +vt 0.000000 0.687500 +vt 0.000000 0.812500 +vt -1.000000 0.562500 +vt 0.875000 0.812500 +vt 0.875000 0.687500 +vt 0.250000 0.312500 +vt 0.562500 0.187500 +vt 0.250000 0.187500 +vt -1.000000 0.187500 +vt 0.312500 0.625000 +vt 0.312500 0.187500 +vt 0.312500 -0.187500 +vt 1.000000 -0.187500 +vt 0.687500 0.500000 +vt -0.000000 1.000000 +vt 0.000000 0.875000 +vt 0.437500 0.500000 +vt -1.000000 0.625000 +vt 0.812500 0.187500 +vt 1.187500 0.187500 +vt 1.187500 0.312500 +vt 1.312500 0.312500 +vt 1.312500 0.687500 +vt 0.687500 0.187500 +vt 0.687500 0.312500 +vt 1.187500 0.812500 +vt 0.812500 0.812500 +vt 0.187500 0.312500 +vt 0.312500 0.687500 +vt 0.687500 0.687500 +vt -0.187500 0.187500 +vt 0.187500 0.187500 +vt -0.312500 0.687500 +vt -0.312500 0.312500 +vt 0.187500 0.812500 +vt -0.187500 0.812500 +vt 0.437500 0.687500 +vt 0.437500 0.187500 +vt 0.562500 0.812500 +vt 0.562500 0.687500 +vt 0.312500 0.562500 +vt 1.000000 0.875000 +vt 0.375000 0.062500 +vt -1.000000 0.375000 +vt 0.625000 0.500000 +vt 0.875000 0.562500 +vt 0.937500 0.812500 +vt 0.937500 0.687500 +vt 0.875000 0.937500 +vt 0.562500 0.312500 +vn -1.000000 0.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -0.002100 -1.000000 +vn 0.001200 -1.000000 0.000000 +vn 0.000000 0.002800 -1.000000 +vn -0.001200 -1.000000 0.000200 +g boats_boat_boats_boat_None +usemtl None +s off +f 41/1/1 27/2/1 43/3/1 +f 76/4/2 74/5/2 72/6/2 +f 8/7/2 6/1/2 5/8/2 +f 15/9/1 13/10/1 16/11/1 +f 51/12/3 71/13/3 50/14/3 +f 56/15/2 32/16/2 53/17/2 +f 15/18/3 8/19/3 23/20/3 +f 22/21/2 40/22/2 39/23/2 +f 19/24/4 2/25/4 53/26/4 +f 70/27/5 62/28/5 69/29/5 +f 11/30/5 19/31/5 10/32/5 +f 4/15/5 20/33/5 17/34/5 +f 72/35/3 64/36/3 63/37/3 +f 13/8/5 7/38/5 16/7/5 +f 23/39/6 47/11/6 44/9/6 +f 68/40/7 70/41/7 69/42/7 +f 80/43/8 40/10/8 30/11/8 +f 3/15/1 1/32/1 4/30/1 +f 20/44/2 18/27/2 17/45/2 +f 74/17/5 65/46/5 64/47/5 +f 31/43/1 54/47/1 52/48/1 +f 22/47/5 14/43/5 15/48/5 +f 46/1/2 23/7/2 44/8/2 +f 57/21/1 38/22/1 58/49/1 +f 61/50/9 76/51/9 73/52/9 +f 37/45/5 2/23/5 3/21/5 +f 78/28/3 67/53/3 65/54/3 +f 64/5/1 66/4/1 63/6/1 +f 76/55/6 67/56/6 77/57/6 +f 47/17/2 26/10/2 45/11/2 +f 5/16/5 26/47/5 8/17/5 +f 33/58/6 48/59/6 55/60/6 +f 29/38/2 42/3/2 49/29/2 +f 32/44/6 52/21/6 53/45/6 +f 58/15/6 34/33/6 56/34/6 +f 27/7/6 46/29/6 43/8/6 +f 73/61/6 68/62/6 61/63/6 +f 21/58/6 42/29/6 28/38/6 +f 11/29/1 9/58/1 12/27/1 +f 59/45/1 36/2/1 60/3/1 +f 60/9/6 35/10/6 57/11/6 +f 41/1/1 21/64/1 27/2/1 +f 72/6/2 48/65/2 50/66/2 +f 50/66/2 71/67/2 70/68/2 +f 70/68/2 75/17/2 73/69/2 +f 76/4/2 77/70/2 74/5/2 +f 77/70/2 78/71/2 74/5/2 +f 50/66/2 70/68/2 73/69/2 +f 73/69/2 76/4/2 72/6/2 +f 72/6/2 50/66/2 73/69/2 +f 8/7/2 7/64/2 6/1/2 +f 15/9/1 14/39/1 13/10/1 +f 51/12/3 62/72/3 71/13/3 +f 56/15/2 34/73/2 32/16/2 +f 32/26/3 34/74/3 38/75/3 +f 35/76/3 36/77/3 37/78/3 +f 32/26/3 38/75/3 35/76/3 +f 29/66/3 33/79/3 31/80/3 +f 32/26/3 35/76/3 3/25/3 +f 28/51/3 29/66/3 31/80/3 +f 31/80/3 32/26/3 18/24/3 +f 3/25/3 4/81/3 17/82/3 +f 35/76/3 37/78/3 3/25/3 +f 21/83/3 28/51/3 22/84/3 +f 3/25/3 17/82/3 18/24/3 +f 11/85/3 12/55/3 30/52/3 +f 32/26/3 3/25/3 18/24/3 +f 11/85/3 30/52/3 22/84/3 +f 31/80/3 18/24/3 11/85/3 +f 24/86/3 27/87/3 21/83/3 +f 28/51/3 31/80/3 11/85/3 +f 11/85/3 22/84/3 28/51/3 +f 24/86/3 21/83/3 23/20/3 +f 26/88/3 25/89/3 23/20/3 +f 23/20/3 21/83/3 15/18/3 +f 15/18/3 16/90/3 7/91/3 +f 21/83/3 22/84/3 15/18/3 +f 8/19/3 26/88/3 23/20/3 +f 15/18/3 7/91/3 8/19/3 +f 22/21/2 30/49/2 40/22/2 +f 47/89/4 45/88/4 5/19/4 +f 5/19/4 6/91/4 13/90/4 +f 5/19/4 13/90/4 14/18/4 +f 44/20/4 47/89/4 5/19/4 +f 43/87/4 46/86/4 44/20/4 +f 41/83/4 43/87/4 44/20/4 +f 44/20/4 5/19/4 14/18/4 +f 39/84/4 40/52/4 80/50/4 +f 44/20/4 14/18/4 41/83/4 +f 42/51/4 41/83/4 39/84/4 +f 39/84/4 80/50/4 50/92/4 +f 41/83/4 14/18/4 39/84/4 +f 48/93/4 49/66/4 42/51/4 +f 50/92/4 48/93/4 42/51/4 +f 80/50/4 79/94/4 50/92/4 +f 50/92/4 42/51/4 39/84/4 +f 54/79/4 55/62/4 52/80/4 +f 50/92/4 79/94/4 51/95/4 +f 52/80/4 55/62/4 51/95/4 +f 51/95/4 79/94/4 10/85/4 +f 79/94/4 9/55/4 10/85/4 +f 53/26/4 52/80/4 10/85/4 +f 58/75/4 56/74/4 53/26/4 +f 59/78/4 60/77/4 57/76/4 +f 57/76/4 58/75/4 53/26/4 +f 52/80/4 51/95/4 10/85/4 +f 19/24/4 20/82/4 1/81/4 +f 53/26/4 10/85/4 19/24/4 +f 59/78/4 57/76/4 2/25/4 +f 19/24/4 1/81/4 2/25/4 +f 2/25/4 57/76/4 53/26/4 +f 70/27/5 71/96/5 62/28/5 +f 11/30/5 18/97/5 19/31/5 +f 4/15/5 1/73/5 20/33/5 +f 72/35/3 74/54/3 64/36/3 +f 13/8/5 6/29/5 7/38/5 +f 23/39/6 25/10/6 47/11/6 +f 68/40/7 75/98/7 70/41/7 +f 30/11/5 12/17/5 79/99/5 +f 79/99/10 80/43/10 30/11/10 +f 12/17/5 9/16/5 79/99/5 +f 3/15/1 2/73/1 1/32/1 +f 20/44/2 19/58/2 18/27/2 +f 74/17/5 78/100/5 65/46/5 +f 31/43/1 33/99/1 54/47/1 +f 22/47/5 39/99/5 14/43/5 +f 46/1/2 24/64/2 23/7/2 +f 57/21/1 35/23/1 38/22/1 +f 61/50/9 66/53/9 76/51/9 +f 37/45/5 59/44/5 2/23/5 +f 78/28/3 77/51/3 67/53/3 +f 62/67/1 51/66/1 69/68/1 +f 51/66/1 55/65/1 63/6/1 +f 68/17/1 69/68/1 61/69/1 +f 61/69/1 69/68/1 51/66/1 +f 61/69/1 51/66/1 63/6/1 +f 65/71/1 67/70/1 64/5/1 +f 61/69/1 63/6/1 66/4/1 +f 64/5/1 67/70/1 66/4/1 +f 76/55/6 66/85/6 67/56/6 +f 47/17/2 25/16/2 26/10/2 +f 5/16/5 45/99/5 26/47/5 +f 55/60/6 54/101/6 33/58/6 +f 33/58/6 29/22/6 48/59/6 +f 48/59/6 72/102/6 63/103/6 +f 29/22/6 49/104/6 48/59/6 +f 48/59/6 63/103/6 55/60/6 +f 29/38/2 28/2/2 42/3/2 +f 32/44/6 31/23/6 52/21/6 +f 58/15/6 38/73/6 34/33/6 +f 27/7/6 24/38/6 46/29/6 +f 73/61/6 75/105/6 68/62/6 +f 21/58/6 41/27/6 42/29/6 +f 11/29/1 10/38/1 9/58/1 +f 59/45/1 37/44/1 36/2/1 +f 60/9/6 36/39/6 35/10/6 diff --git a/mods/boats/textures/boats_inventory.png b/mods/boats/textures/boats_inventory.png new file mode 100644 index 0000000..f9d082e Binary files /dev/null and b/mods/boats/textures/boats_inventory.png differ diff --git a/mods/boats/textures/boats_wield.png b/mods/boats/textures/boats_wield.png new file mode 100644 index 0000000..f998b5b Binary files /dev/null and b/mods/boats/textures/boats_wield.png differ diff --git a/mods/bones/README.txt b/mods/bones/README.txt new file mode 100644 index 0000000..91bcd10 --- /dev/null +++ b/mods/bones/README.txt @@ -0,0 +1,12 @@ +Minetest Game mod: bones +======================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by PilzAdam (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +All textures: paramat (CC BY-SA 3.0) diff --git a/mods/bones/depends.txt b/mods/bones/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/bones/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/bones/init.lua b/mods/bones/init.lua new file mode 100644 index 0000000..859ead8 --- /dev/null +++ b/mods/bones/init.lua @@ -0,0 +1,287 @@ +-- Minetest 0.4 mod: bones +-- See README.txt for licensing and other information. + +bones = {} + +local function is_owner(pos, name) + local owner = minetest.get_meta(pos):get_string("owner") + if owner == "" or owner == name or minetest.check_player_privs(name, "protection_bypass") then + return true + end + return false +end + +local bones_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 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", + tiles = { + "bones_top.png^[transform2", + "bones_bottom.png", + "bones_side.png", + "bones_side.png", + "bones_rear.png", + "bones_front.png" + }, + paramtype2 = "facedir", + groups = {dig_immediate = 2}, + sounds = default.node_sound_gravel_defaults(), + + can_dig = function(pos, player) + local inv = minetest.get_meta(pos):get_inventory() + local name = "" + if player then + name = player:get_player_name() + end + return is_owner(pos, name) and inv:is_empty("main") + end, + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + if is_owner(pos, player:get_player_name()) then + return count + end + return 0 + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + return 0 + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + if is_owner(pos, player:get_player_name()) then + return stack:get_count() + end + return 0 + end, + + on_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if meta:get_inventory():is_empty("main") then + local inv = player:get_inventory() + if inv:room_for_item("main", {name = "bones:bones"}) then + inv:add_item("main", {name = "bones:bones"}) + else + minetest.add_item(pos, "bones:bones") + end + minetest.remove_node(pos) + end + end, + + on_punch = function(pos, node, player) + if not is_owner(pos, player:get_player_name()) then + return + end + + if minetest.get_meta(pos):get_string("infotext") == "" then + return + end + + local inv = minetest.get_meta(pos):get_inventory() + local player_inv = player:get_inventory() + local has_space = true + + for i = 1, inv:get_size("main") do + local stk = inv:get_stack("main", i) + if player_inv:room_for_item("main", stk) then + inv:set_stack("main", i, nil) + player_inv:add_item("main", stk) + else + has_space = false + break + end + end + + -- remove bones if player emptied them + if has_space then + if player_inv:room_for_item("main", {name = "bones:bones"}) then + player_inv:add_item("main", {name = "bones:bones"}) + else + minetest.add_item(pos,"bones:bones") + end + minetest.remove_node(pos) + end + end, + + on_timer = function(pos, elapsed) + local meta = minetest.get_meta(pos) + local time = meta:get_int("time") + elapsed + if time >= share_bones_time then + meta:set_string("infotext", meta:get_string("owner") .. "'s old bones") + meta:set_string("owner", "") + else + meta:set_int("time", time) + return true + end + end, + on_blast = function(pos) + end, +}) + +local function may_replace(pos, player) + local node_name = minetest.get_node(pos).name + local node_definition = minetest.registered_nodes[node_name] + + -- if the node is unknown, we return false + if not node_definition then + return false + end + + -- allow replacing air and liquids + if node_name == "air" or node_definition.liquidtype ~= "none" then + return true + end + + -- don't replace filled chests and other nodes that don't allow it + local can_dig_func = node_definition.can_dig + if can_dig_func and not can_dig_func(pos, player) then + return false + end + + -- default to each nodes buildable_to; if a placed block would replace it, why shouldn't bones? + -- flowers being squished by bones are more realistical than a squished stone, too + -- exception are of course any protected buildable_to + return node_definition.buildable_to and not minetest.is_protected(pos, player:get_player_name()) +end + +local drop = function(pos, itemstack) + local obj = minetest.add_item(pos, itemstack:take_item(itemstack:get_count())) + if obj then + obj:set_velocity({ + x = math.random(-10, 10) / 9, + y = 5, + z = math.random(-10, 10) / 9, + }) + end +end + +local player_inventory_lists = { "main", "craft" } +bones.player_inventory_lists = player_inventory_lists + +local function is_all_empty(player_inv) + for _, list_name in ipairs(player_inventory_lists) do + if not player_inv:is_empty(list_name) then + return false + end + end + return true +end + +minetest.register_on_dieplayer(function(player) + if not player then + return + end + -- TODO FIXME Don't kill dead players? + 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 + + local bones_position_message = minetest.settings:get_bool("bones_position_message") == true + local player_name = player:get_player_name() + local pos = vector.round(player:get_pos()) + local pos_string = minetest.pos_to_string(pos) + + -- return if keep inventory set or in creative mode + if bones_mode == "keep" or (creative and creative.is_enabled_for + and creative.is_enabled_for(player:get_player_name())) then + --[[minetest.log("action", player_name .. " dies at " .. pos_string .. + ". No bones placed")]] + if bones_position_message then + minetest.chat_send_player(player_name, player_name .. " died at " .. pos_string .. ".") + end + return + end + + local player_inv = player:get_inventory() + if is_all_empty(player_inv) then + minetest.log("action", player_name .. " dies at " .. pos_string .. + ". No bones placed") + if bones_position_message then + minetest.chat_send_player(player_name, player_name .. " died at " .. pos_string .. ".") + end + return + end + + -- check if it's possible to place bones, if not find space near player + if bones_mode == "bones" and not may_replace(pos, player) then + local air = minetest.find_node_near(pos, 1, {"air"}) + if air and not minetest.is_protected(air, player_name) then + pos = air + else + bones_mode = "drop" + end + end + + if bones_mode == "drop" then + for _, list_name in ipairs(player_inventory_lists) do + for i = 1, player_inv:get_size(list_name) do + drop(pos, player_inv:get_stack(list_name, i)) + end + player_inv:set_list(list_name, {}) + end + drop(pos, ItemStack("bones:bones")) + minetest.log("action", player_name .. " dies at " .. pos_string .. + ". Inventory dropped") + if bones_position_message then + minetest.chat_send_player(player_name, player_name .. " died at " .. pos_string .. + ", and dropped their inventory.") + end + return + end + + local param2 = minetest.dir_to_facedir(player:get_look_dir()) + minetest.set_node(pos, {name = "bones:bones", param2 = param2}) + + minetest.log("action", player_name .. " dies at " .. pos_string .. + ". Bones placed") + if bones_position_message then + minetest.chat_send_player(player_name, player_name .. " died at " .. pos_string .. + ", and bones were placed.") + end + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("main", 8 * 4) + + for _, list_name in ipairs(player_inventory_lists) do + for i = 1, player_inv:get_size(list_name) do + local stack = player_inv:get_stack(list_name, i) + if inv:room_for_item("main", stack) then + inv:add_item("main", stack) + else -- no space left + drop(pos, stack) + end + end + player_inv:set_list(list_name, {}) + end + + meta:set_string("formspec", bones_formspec) + meta:set_string("owner", player_name) + + if share_bones_time ~= 0 then + meta:set_string("infotext", player_name .. "'s fresh bones") + + if share_bones_time_early == 0 or not minetest.is_protected(pos, player_name) then + meta:set_int("time", 0) + else + meta:set_int("time", (share_bones_time - share_bones_time_early)) + end + + minetest.get_node_timer(pos):start(10) + else + meta:set_string("infotext", player_name.."'s bones") + end +end) diff --git a/mods/bones/license.txt b/mods/bones/license.txt new file mode 100644 index 0000000..fe52584 --- /dev/null +++ b/mods/bones/license.txt @@ -0,0 +1,58 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2016 paramat + +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. + diff --git a/mods/bones/textures/bones_bottom.png b/mods/bones/textures/bones_bottom.png new file mode 100644 index 0000000..859c6bb Binary files /dev/null and b/mods/bones/textures/bones_bottom.png differ diff --git a/mods/bones/textures/bones_front.png b/mods/bones/textures/bones_front.png new file mode 100644 index 0000000..1e52437 Binary files /dev/null and b/mods/bones/textures/bones_front.png differ diff --git a/mods/bones/textures/bones_rear.png b/mods/bones/textures/bones_rear.png new file mode 100644 index 0000000..4cfe236 Binary files /dev/null and b/mods/bones/textures/bones_rear.png differ diff --git a/mods/bones/textures/bones_side.png b/mods/bones/textures/bones_side.png new file mode 100644 index 0000000..a07595f Binary files /dev/null and b/mods/bones/textures/bones_side.png differ diff --git a/mods/bones/textures/bones_top.png b/mods/bones/textures/bones_top.png new file mode 100644 index 0000000..198a8a2 Binary files /dev/null and b/mods/bones/textures/bones_top.png differ diff --git a/mods/bucket/README.txt b/mods/bucket/README.txt new file mode 100644 index 0000000..58997b2 --- /dev/null +++ b/mods/bucket/README.txt @@ -0,0 +1,13 @@ +Minetest Game mod: bucket +========================= +See license.txt for license information. + +Authors of source code +---------------------- +Kahrl (LGPLv2.1+) +celeron55, Perttu Ahola (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures) +--------------------------- +ElementW (CC BY-SA 3.0) diff --git a/mods/bucket/depends.txt b/mods/bucket/depends.txt new file mode 100644 index 0000000..3a7daa1 --- /dev/null +++ b/mods/bucket/depends.txt @@ -0,0 +1,2 @@ +default + diff --git a/mods/bucket/init.lua b/mods/bucket/init.lua new file mode 100644 index 0000000..1d37cb4 --- /dev/null +++ b/mods/bucket/init.lua @@ -0,0 +1,222 @@ +-- Minetest 0.4 mod: bucket +-- See README.txt for licensing and other information. + +minetest.register_alias("bucket", "bucket:bucket_empty") +minetest.register_alias("bucket_water", "bucket:bucket_water") +minetest.register_alias("bucket_lava", "bucket:bucket_lava") + +minetest.register_craft({ + output = 'bucket:bucket_empty 1', + recipe = { + {'default:steel_ingot', '', 'default:steel_ingot'}, + {'', 'default:steel_ingot', ''}, + } +}) + +bucket = {} +bucket.liquids = {} + +local function check_protection(pos, name, text) + if minetest.is_protected(pos, name) then + minetest.log("action", (name ~= "" and name or "A mod") + .. " tried to " .. text + .. " at protected position " + .. minetest.pos_to_string(pos) + .. " with a bucket") + minetest.record_protection_violation(pos, name) + return true + end + return false +end + +-- Register a new liquid +-- source = name of the source node +-- flowing = name of the flowing node +-- itemname = name of the new bucket item (or nil if liquid is not takeable) +-- inventory_image = texture of the new bucket item (ignored if itemname == nil) +-- name = text description of the bucket item +-- groups = (optional) groups of the bucket item, for example {water_bucket = 1} +-- force_renew = (optional) bool. Force the liquid source to renew if it has a +-- source neighbour, even if defined as 'liquid_renewable = false'. +-- Needed to avoid creating holes in sloping rivers. +-- This function can be called from any mod (that depends on bucket). +function bucket.register_liquid(source, flowing, itemname, inventory_image, name, + groups, force_renew) + bucket.liquids[source] = { + source = source, + flowing = flowing, + itemname = itemname, + force_renew = force_renew, + } + bucket.liquids[flowing] = bucket.liquids[source] + + if itemname ~= nil then + minetest.register_craftitem(itemname, { + description = name, + inventory_image = inventory_image, + stack_max = 1, + liquids_pointable = true, + groups = groups, + + on_place = function(itemstack, user, pointed_thing) + -- Must be pointing to node + if pointed_thing.type ~= "node" then + return + end + + local node = minetest.get_node_or_nil(pointed_thing.under) + local ndef = node and minetest.registered_nodes[node.name] + + -- Call on_rightclick if the pointed node defines it + if ndef and ndef.on_rightclick and + not (user and user:is_player() and + user:get_player_control().sneak) then + return ndef.on_rightclick( + pointed_thing.under, + node, user, + itemstack) + end + + local lpos + + -- Check if pointing to a buildable node + if ndef and ndef.buildable_to then + -- buildable; replace the node + lpos = pointed_thing.under + else + -- not buildable to; place the liquid above + -- check if the node above can be replaced + + lpos = pointed_thing.above + node = minetest.get_node_or_nil(lpos) + local above_ndef = node and minetest.registered_nodes[node.name] + + if not above_ndef or not above_ndef.buildable_to then + -- do not remove the bucket with the liquid + return itemstack + end + end + + if check_protection(lpos, user + and user:get_player_name() + or "", "place "..source) then + return + end + + minetest.set_node(lpos, {name = source}) + return ItemStack("bucket:bucket_empty") + end + }) + end +end + +minetest.register_craftitem("bucket:bucket_empty", { + description = "Empty Bucket", + inventory_image = "bucket.png", + stack_max = 99, + liquids_pointable = true, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type == "object" then + pointed_thing.ref:punch(user, 1.0, { full_punch_interval=1.0 }, nil) + return user:get_wielded_item() + elseif pointed_thing.type ~= "node" then + -- do nothing if it's neither object nor node + return + end + -- Check if pointing to a liquid source + local node = minetest.get_node(pointed_thing.under) + local liquiddef = bucket.liquids[node.name] + local item_count = user:get_wielded_item():get_count() + + if liquiddef ~= nil + and liquiddef.itemname ~= nil + and node.name == liquiddef.source then + if check_protection(pointed_thing.under, + user:get_player_name(), + "take ".. node.name) then + return + end + + -- default set to return filled bucket + local giving_back = liquiddef.itemname + + -- check if holding more than 1 empty bucket + if item_count > 1 then + + -- if space in inventory add filled bucked, otherwise drop as item + local inv = user:get_inventory() + if inv:room_for_item("main", {name=liquiddef.itemname}) then + inv:add_item("main", liquiddef.itemname) + else + local pos = user:get_pos() + pos.y = math.floor(pos.y + 0.5) + minetest.add_item(pos, liquiddef.itemname) + end + + -- set to return empty buckets minus 1 + giving_back = "bucket:bucket_empty "..tostring(item_count-1) + + end + + -- force_renew requires a source neighbour + local source_neighbor = false + if liquiddef.force_renew then + source_neighbor = + minetest.find_node_near(pointed_thing.under, 1, liquiddef.source) + end + if not (source_neighbor and liquiddef.force_renew) then + minetest.add_node(pointed_thing.under, {name = "air"}) + end + + return ItemStack(giving_back) + else + -- non-liquid nodes will have their on_punch triggered + local node_def = minetest.registered_nodes[node.name] + if node_def then + node_def.on_punch(pointed_thing.under, node, user, pointed_thing) + end + return user:get_wielded_item() + end + end, +}) + +bucket.register_liquid( + "default:water_source", + "default:water_flowing", + "bucket:bucket_water", + "bucket_water.png", + "Water Bucket", + {water_bucket = 1} +) + +-- River water source is 'liquid_renewable = false' to avoid horizontal spread +-- of water sources in sloping rivers that can cause water to overflow +-- riverbanks and cause floods. +-- River water source is instead made renewable by the 'force renew' option +-- used here. + +bucket.register_liquid( + "default:river_water_source", + "default:river_water_flowing", + "bucket:bucket_river_water", + "bucket_river_water.png", + "River Water Bucket", + {water_bucket = 1}, + true +) + +bucket.register_liquid( + "default:lava_source", + "default:lava_flowing", + "bucket:bucket_lava", + "bucket_lava.png", + "Lava Bucket" +) + +minetest.register_craft({ + type = "fuel", + recipe = "bucket:bucket_lava", + burntime = 60, + replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}}, +}) + diff --git a/mods/bucket/license.txt b/mods/bucket/license.txt new file mode 100644 index 0000000..a5156ae --- /dev/null +++ b/mods/bucket/license.txt @@ -0,0 +1,51 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2011-2016 Kahrl +Copyright (C) 2011-2016 celeron55, Perttu Ahola +Copyright (C) 2011-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) 2015-2016 ElementW + +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/bucket/textures/bucket.png b/mods/bucket/textures/bucket.png new file mode 100755 index 0000000..17b0c49 Binary files /dev/null and b/mods/bucket/textures/bucket.png differ diff --git a/mods/bucket/textures/bucket_lava.png b/mods/bucket/textures/bucket_lava.png new file mode 100644 index 0000000..ac6108d Binary files /dev/null and b/mods/bucket/textures/bucket_lava.png differ diff --git a/mods/bucket/textures/bucket_river_water.png b/mods/bucket/textures/bucket_river_water.png new file mode 100644 index 0000000..d4648bb Binary files /dev/null and b/mods/bucket/textures/bucket_river_water.png differ diff --git a/mods/bucket/textures/bucket_water.png b/mods/bucket/textures/bucket_water.png new file mode 100644 index 0000000..5af836b Binary files /dev/null and b/mods/bucket/textures/bucket_water.png differ diff --git a/mods/butterflies/README.txt b/mods/butterflies/README.txt new file mode 100644 index 0000000..a7f52a0 --- /dev/null +++ b/mods/butterflies/README.txt @@ -0,0 +1,14 @@ +Minetest Game mod: Butterflies +============================== +Adds butterflies to the world on mapgen, which can be caught in a net if the +fireflies mod is also enabled. + +Authors of source code +---------------------- +Shara RedCat (MIT) + +Authors of media (textures) +--------------------------- +Shara RedCat (CC BY-SA 3.0): + butterflies_butterfly_*.png + butterflies_butterfly_*_animated.png \ No newline at end of file diff --git a/mods/butterflies/depends.txt b/mods/butterflies/depends.txt new file mode 100644 index 0000000..df07aca --- /dev/null +++ b/mods/butterflies/depends.txt @@ -0,0 +1,2 @@ +default +flowers \ No newline at end of file diff --git a/mods/butterflies/init.lua b/mods/butterflies/init.lua new file mode 100644 index 0000000..008211e --- /dev/null +++ b/mods/butterflies/init.lua @@ -0,0 +1,133 @@ +-- register butterflies +local butter_list = { + {"white", "White"}, + {"red", "Red"}, + {"violet", "Violet"} +} + +for i in ipairs (butter_list) do + local name = butter_list[i][1] + local desc = butter_list[i][2] + + minetest.register_node("butterflies:butterfly_"..name, { + description = desc.." Butterfly", + drawtype = "plantlike", + tiles = {{ + name = "butterflies_butterfly_"..name.."_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3 + }, + }}, + inventory_image = "butterflies_butterfly_"..name..".png", + wield_image = "butterflies_butterfly_"..name..".png", + waving = 1, + paramtype = "light", + sunlight_propagates = true, + buildable_to = true, + walkable = false, + groups = {catchable = 1}, + selection_box = { + type = "fixed", + fixed = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1}, + }, + floodable = true, + on_place = function(itemstack, placer, pointed_thing) + local player_name = placer:get_player_name() + local pos = pointed_thing.above + + if not minetest.is_protected(pos, player_name) and + not minetest.is_protected(pointed_thing.under, player_name) and + minetest.get_node(pos).name == "air" then + minetest.set_node(pos, {name = "butterflies:butterfly_"..name}) + minetest.get_node_timer(pos):start(1) + itemstack:take_item() + end + return itemstack + end, + on_timer = function(pos, elapsed) + if minetest.get_node_light(pos) < 11 then + minetest.set_node(pos, {name = "butterflies:hidden_butterfly_"..name}) + end + minetest.get_node_timer(pos):start(30) + end + }) + + minetest.register_node("butterflies:hidden_butterfly_"..name, { + description = "Hidden "..desc.." Butterfly", + drawtype = "airlike", + inventory_image = "insects_butterfly_"..name..".png", + wield_image = "insects_butterfly_"..name..".png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + pointable = false, + diggable = false, + drop = "", + groups = {not_in_creative_inventory = 1}, + floodable = true, + on_place = function(itemstack, placer, pointed_thing) + local player_name = placer:get_player_name() + local pos = pointed_thing.above + + if not minetest.is_protected(pos, player_name) and + not minetest.is_protected(pointed_thing.under, player_name) and + minetest.get_node(pos).name == "air" then + minetest.set_node(pos, {name = "butterflies:hidden_butterfly_"..name}) + minetest.get_node_timer(pos):start(1) + itemstack:take_item() + end + return itemstack + end, + on_timer = function(pos, elapsed) + if minetest.get_node_light(pos) >= 11 then + minetest.set_node(pos, {name = "butterflies:butterfly_"..name}) + end + minetest.get_node_timer(pos):start(30) + end + }) +end + +-- register decoration +minetest.register_decoration({ + name = "butterflies:butterfly", + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + place_offset_y = 2, + sidelen = 80, + fill_ratio = 0.005, + biomes = {"grassland", "deciduous_forest", "floatland_grassland"}, + y_max = 31000, + y_min = 1, + decoration = { + "butterflies:butterfly_white", + "butterflies:butterfly_red", + "butterflies:butterfly_violet" + }, + spawn_by = "group:flower", + num_spawn_by = 1 +}) + +-- get decoration ID +local butterflies = minetest.get_decoration_id("butterflies:butterfly") +minetest.set_gen_notify({decoration = true}, {butterflies}) + +-- start nodetimers +minetest.register_on_generated(function(minp, maxp, blockseed) + local gennotify = minetest.get_mapgen_object("gennotify") + local poslist = {} + + for _, pos in ipairs(gennotify["decoration#"..butterflies] or {}) do + local deco_pos = {x = pos.x, y = pos.y + 3, z = pos.z} + table.insert(poslist, deco_pos) + end + + if #poslist ~= 0 then + for i = 1, #poslist do + local pos = poslist[i] + minetest.get_node_timer(pos):start(1) + end + end +end) diff --git a/mods/butterflies/license.txt b/mods/butterflies/license.txt new file mode 100644 index 0000000..eebdad6 --- /dev/null +++ b/mods/butterflies/license.txt @@ -0,0 +1,58 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (c) 2018 Shara RedCat + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2018 Shara RedCat + +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/ \ No newline at end of file diff --git a/mods/butterflies/textures/butterflies_butterfly_red.png b/mods/butterflies/textures/butterflies_butterfly_red.png new file mode 100644 index 0000000..8edfc36 Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_red.png differ diff --git a/mods/butterflies/textures/butterflies_butterfly_red_animated.png b/mods/butterflies/textures/butterflies_butterfly_red_animated.png new file mode 100644 index 0000000..4a2097b Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_red_animated.png differ diff --git a/mods/butterflies/textures/butterflies_butterfly_violet.png b/mods/butterflies/textures/butterflies_butterfly_violet.png new file mode 100644 index 0000000..8b8c29d Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_violet.png differ diff --git a/mods/butterflies/textures/butterflies_butterfly_violet_animated.png b/mods/butterflies/textures/butterflies_butterfly_violet_animated.png new file mode 100644 index 0000000..3f9d72e Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_violet_animated.png differ diff --git a/mods/butterflies/textures/butterflies_butterfly_white.png b/mods/butterflies/textures/butterflies_butterfly_white.png new file mode 100644 index 0000000..db4eaec Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_white.png differ diff --git a/mods/butterflies/textures/butterflies_butterfly_white_animated.png b/mods/butterflies/textures/butterflies_butterfly_white_animated.png new file mode 100644 index 0000000..e7cada3 Binary files /dev/null and b/mods/butterflies/textures/butterflies_butterfly_white_animated.png differ diff --git a/mods/carts/README.txt b/mods/carts/README.txt new file mode 100644 index 0000000..c0be2d7 --- /dev/null +++ b/mods/carts/README.txt @@ -0,0 +1,23 @@ +Carts (formerly boost_cart) +========================== + +Carts, based almost entirely on the mod boost_cart [1], which +itself is based on (and fully compatible with) the carts mod [2]. + +The model was originally designed by stujones11 [3] (CC-0). + +Cart textures are based on original work from PixelBOX by Gambit (permissive +license). + + +[1] https://github.com/SmallJoker/boost_cart/ +[2] https://github.com/PilzAdam/carts/ +[3] https://github.com/stujones11/railcart/ + + +Features +---------- +- A fast cart for your railway or roller coaster (up to 7 m/s!) +- Boost and brake rails +- Rail junction switching with the 'right-left' walking keys +- Handbrake with the 'back' key diff --git a/mods/carts/cart_entity.lua b/mods/carts/cart_entity.lua new file mode 100644 index 0000000..855450d --- /dev/null +++ b/mods/carts/cart_entity.lua @@ -0,0 +1,428 @@ +local cart_entity = { + initial_properties = { + physical = false, -- otherwise going uphill breaks + collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + visual = "mesh", + mesh = "carts_cart.b3d", + visual_size = {x=1, y=1}, + textures = {"carts_cart.png"}, + }, + + driver = nil, + punched = false, -- used to re-send velocity and position + velocity = {x=0, y=0, z=0}, -- only used on punch + old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch + old_pos = nil, + old_switch = 0, + railtype = nil, + attached_items = {} +} + +function cart_entity:on_rightclick(clicker) + if not clicker or not clicker:is_player() then + return + end + local player_name = clicker:get_player_name() + if self.driver and player_name == self.driver then + self.driver = nil + carts:manage_attachment(clicker, nil) + elseif not self.driver then + self.driver = player_name + carts:manage_attachment(clicker, self.object) + + -- player_api does not update the animation + -- when the player is attached, reset to default animation + player_api.set_animation(clicker, "stand") + end +end + +function cart_entity:on_activate(staticdata, dtime_s) + self.object:set_armor_groups({immortal=1}) + if string.sub(staticdata, 1, string.len("return")) ~= "return" then + return + end + local data = minetest.deserialize(staticdata) + if type(data) ~= "table" then + return + end + self.railtype = data.railtype + if data.old_dir then + self.old_dir = data.old_dir + end +end + +function cart_entity:get_staticdata() + return minetest.serialize({ + railtype = self.railtype, + old_dir = self.old_dir + }) +end + +-- 0.5.x and later: When the driver leaves +function cart_entity:on_detach_child(child) + if child and child:get_player_name() == self.driver then + self.driver = nil + end +end + +function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction) + local pos = self.object:get_pos() + local vel = self.object:get_velocity() + if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then + local node = minetest.get_node(pos).name + self.railtype = minetest.get_item_group(node, "connect_to_raillike") + end + -- Punched by non-player + if not puncher or not puncher:is_player() then + local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + self.velocity = vector.multiply(cart_dir, 2) + self.punched = true + return + end + -- Player digs cart by sneak-punch + if puncher:get_player_control().sneak then + if self.sound_handle then + minetest.sound_stop(self.sound_handle) + end + -- Detach driver and items + if self.driver then + if self.old_pos then + self.object:set_pos(self.old_pos) + end + local player = minetest.get_player_by_name(self.driver) + carts:manage_attachment(player, nil) + end + for _, obj_ in ipairs(self.attached_items) do + if obj_ then + obj_:set_detach() + end + end + -- Pick up cart + local inv = puncher:get_inventory() + 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 + if not leftover:is_empty() then + minetest.add_item(self.object:get_pos(), leftover) + end + end + self.object:remove() + return + end + -- Player punches cart to alter velocity + if puncher:get_player_name() == self.driver then + if math.abs(vel.x + vel.z) > carts.punch_speed_max then + return + end + end + + local punch_dir = carts:velocity_to_dir(puncher:get_look_dir()) + punch_dir.y = 0 + local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype) + if vector.equals(cart_dir, {x=0, y=0, z=0}) then + return + end + + local punch_interval = 1 + if tool_capabilities and tool_capabilities.full_punch_interval then + punch_interval = tool_capabilities.full_punch_interval + end + time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval) + local f = 2 * (time_from_last_punch / punch_interval) + + self.velocity = vector.multiply(cart_dir, f) + self.old_dir = cart_dir + self.punched = true +end + +local function rail_on_step_event(handler, obj, dtime) + if handler then + handler(obj, dtime) + end +end + +-- sound refresh interval = 1.0sec +local function rail_sound(self, dtime) + if not self.sound_ttl then + self.sound_ttl = 1.0 + return + elseif self.sound_ttl > 0 then + self.sound_ttl = self.sound_ttl - dtime + return + end + self.sound_ttl = 1.0 + if self.sound_handle then + local handle = self.sound_handle + self.sound_handle = nil + minetest.after(0.2, minetest.sound_stop, handle) + end + local vel = self.object:get_velocity() + local speed = vector.length(vel) + if speed > 0 then + self.sound_handle = minetest.sound_play( + "carts_cart_moving", { + object = self.object, + gain = (speed / carts.speed_max) / 2, + loop = true, + }) + end +end + +local function get_railparams(pos) + local node = minetest.get_node(pos) + return carts.railparams[node.name] or {} +end + +local v3_len = vector.length +local function rail_on_step(self, dtime) + local vel = self.object:get_velocity() + if self.punched then + vel = vector.add(vel, self.velocity) + self.object:set_velocity(vel) + self.old_dir.y = 0 + elseif vector.equals(vel, {x=0, y=0, z=0}) then + return + end + + local pos = self.object:get_pos() + local cart_dir = carts:velocity_to_dir(vel) + local same_dir = vector.equals(cart_dir, self.old_dir) + local update = {} + + if self.old_pos and not self.punched and same_dir then + local flo_pos = vector.round(pos) + local flo_old = vector.round(self.old_pos) + if vector.equals(flo_pos, flo_old) then + -- Do not check one node multiple times + return + end + end + + local ctrl, player + + -- Get player controls + if self.driver then + player = minetest.get_player_by_name(self.driver) + if player then + ctrl = player:get_player_control() + end + end + + local stop_wiggle = false + if self.old_pos and same_dir then + -- Detection for "skipping" nodes (perhaps use average dtime?) + -- It's sophisticated enough to take the acceleration in account + local acc = self.object:get_acceleration() + local distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc)) + + local new_pos, new_dir = carts:pathfinder( + pos, self.old_pos, self.old_dir, distance, ctrl, + self.old_switch, self.railtype + ) + + if new_pos then + -- No rail found: set to the expected position + pos = new_pos + update.pos = true + cart_dir = new_dir + end + elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then + -- Stop wiggle + stop_wiggle = true + end + + local railparams + + -- dir: New moving direction of the cart + -- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node + local dir, switch_keys = carts:get_rail_direction( + pos, cart_dir, ctrl, self.old_switch, self.railtype + ) + local dir_changed = not vector.equals(dir, self.old_dir) + + local new_acc = {x=0, y=0, z=0} + if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then + vel = {x = 0, y = 0, z = 0} + local pos_r = vector.round(pos) + if not carts:is_rail(pos_r, self.railtype) + and self.old_pos then + pos = self.old_pos + elseif not stop_wiggle then + pos = pos_r + else + pos.y = math.floor(pos.y + 0.5) + end + update.pos = true + update.vel = true + else + -- Direction change detected + if dir_changed then + vel = vector.multiply(dir, math.abs(vel.x + vel.z)) + update.vel = true + if dir.y ~= self.old_dir.y then + pos = vector.round(pos) + update.pos = true + end + end + -- Center on the rail + if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then + pos.x = math.floor(pos.x + 0.5) + update.pos = true + end + if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then + pos.z = math.floor(pos.z + 0.5) + update.pos = true + end + + -- Slow down or speed up.. + local acc = dir.y * -4.0 + + -- Get rail for corrected position + railparams = get_railparams(pos) + + -- no need to check for railparams == nil since we always make it exist. + local speed_mod = railparams.acceleration + if speed_mod and speed_mod ~= 0 then + -- Try to make it similar to the original carts mod + acc = acc + speed_mod + else + -- Handbrake or coast + if ctrl and ctrl.down then + acc = acc - 3 + else + acc = acc - 0.4 + end + end + + new_acc = vector.multiply(dir, acc) + end + + -- Limits + local max_vel = carts.speed_max + for _, v in pairs({"x","y","z"}) do + if math.abs(vel[v]) > max_vel then + vel[v] = carts:get_sign(vel[v]) * max_vel + new_acc[v] = 0 + update.vel = true + end + end + + self.object:set_acceleration(new_acc) + self.old_pos = vector.round(pos) + if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then + self.old_dir = vector.new(dir) + end + self.old_switch = switch_keys + + if self.punched then + -- Collect dropped items + for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if not obj_:is_player() and + obj_:get_luaentity() and + not obj_:get_luaentity().physical_state and + obj_:get_luaentity().name == "__builtin:item" then + + obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0}) + self.attached_items[#self.attached_items + 1] = obj_ + end + end + self.punched = false + update.vel = true + end + + railparams = railparams or get_railparams(pos) + + if not (update.vel or update.pos) then + rail_on_step_event(railparams.on_step, self, dtime) + return + end + + local yaw = 0 + if self.old_dir.x < 0 then + yaw = 0.5 + elseif self.old_dir.x > 0 then + yaw = 1.5 + elseif self.old_dir.z < 0 then + yaw = 1 + end + self.object:set_yaw(yaw * math.pi) + + local anim = {x=0, y=0} + if dir.y == -1 then + anim = {x=1, y=1} + elseif dir.y == 1 then + anim = {x=2, y=2} + end + self.object:set_animation(anim, 1, 0) + + if update.vel then + self.object:set_velocity(vel) + end + if update.pos then + if dir_changed then + self.object:set_pos(pos) + else + self.object:move_to(pos) + end + end + + -- call event handler + rail_on_step_event(railparams.on_step, self, dtime) +end + +function cart_entity:on_step(dtime) + rail_on_step(self, dtime) + rail_sound(self, dtime) +end + +minetest.register_entity("carts:cart", cart_entity) + +minetest.register_craftitem("carts:cart", { + description = "Cart (Sneak+Click to pick up)", + 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:is_player() 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 + if carts:is_rail(pointed_thing.under) then + minetest.add_entity(pointed_thing.under, "carts:cart") + elseif carts:is_rail(pointed_thing.above) then + minetest.add_entity(pointed_thing.above, "carts:cart") + else + return + end + + minetest.sound_play({name = "default_place_node_metal", gain = 0.5}, + {pos = pointed_thing.above}) + + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(placer:get_player_name())) then + itemstack:take_item() + end + return itemstack + end, +}) + +minetest.register_craft({ + output = "carts:cart", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + }, +}) diff --git a/mods/carts/depends.txt b/mods/carts/depends.txt new file mode 100644 index 0000000..8e482ce --- /dev/null +++ b/mods/carts/depends.txt @@ -0,0 +1,2 @@ +default +player_api diff --git a/mods/carts/functions.lua b/mods/carts/functions.lua new file mode 100644 index 0000000..a54b594 --- /dev/null +++ b/mods/carts/functions.lua @@ -0,0 +1,248 @@ +function carts:get_sign(z) + if z == 0 then + return 0 + else + return z / math.abs(z) + end +end + +function carts:manage_attachment(player, obj) + if not player then + return + end + local status = obj ~= nil + local player_name = player:get_player_name() + if player_api.player_attached[player_name] == status then + return + end + player_api.player_attached[player_name] = status + + if status then + player:set_attach(obj, "", {x=0, y=-4.5, z=0}, {x=0, y=0, z=0}) + player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0}) + else + player:set_detach() + player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0}) + end +end + +function carts:velocity_to_dir(v) + if math.abs(v.x) > math.abs(v.z) then + return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0} + else + return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)} + end +end + +function carts:is_rail(pos, railtype) + local node = minetest.get_node(pos).name + if node == "ignore" then + local vm = minetest.get_voxel_manip() + local emin, emax = vm:read_from_map(pos, pos) + local area = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax, + } + local data = vm:get_data() + local vi = area:indexp(pos) + node = minetest.get_name_from_content_id(data[vi]) + end + if minetest.get_item_group(node, "rail") == 0 then + return false + end + if not railtype then + return true + end + return minetest.get_item_group(node, "connect_to_raillike") == railtype +end + +function carts:check_front_up_down(pos, dir_, check_up, railtype) + local dir = vector.new(dir_) + local cur + + -- Front + dir.y = 0 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + -- Up + if check_up then + dir.y = 1 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + end + -- Down + dir.y = -1 + cur = vector.add(pos, dir) + if carts:is_rail(cur, railtype) then + return dir + end + return nil +end + +function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype) + local pos = vector.round(pos_) + local cur + local left_check, right_check = true, true + + -- Check left and right + local left = {x=0, y=0, z=0} + local right = {x=0, y=0, z=0} + if dir.z ~= 0 and dir.x == 0 then + left.x = -dir.z + right.x = dir.z + elseif dir.x ~= 0 and dir.z == 0 then + left.z = dir.x + right.z = -dir.x + end + + local straight_priority = ctrl and dir.y ~= 0 + + -- Normal, to disallow rail switching up- & downhill + if straight_priority then + cur = self:check_front_up_down(pos, dir, true, railtype) + if cur then + return cur + end + end + + if ctrl then + if old_switch == 1 then + left_check = false + elseif old_switch == 2 then + right_check = false + end + if ctrl.left and left_check then + cur = self:check_front_up_down(pos, left, false, railtype) + if cur then + return cur, 1 + end + left_check = false + end + if ctrl.right and right_check then + cur = self:check_front_up_down(pos, right, false, railtype) + if cur then + return cur, 2 + end + right_check = true + end + end + + -- Normal + if not straight_priority then + cur = self:check_front_up_down(pos, dir, true, railtype) + if cur then + return cur + end + end + + -- Left, if not already checked + if left_check then + cur = carts:check_front_up_down(pos, left, false, railtype) + if cur then + return cur + end + end + + -- Right, if not already checked + if right_check then + cur = carts:check_front_up_down(pos, right, false, railtype) + if cur then + return cur + end + end + + -- Backwards + if not old_switch then + cur = carts:check_front_up_down(pos, { + x = -dir.x, + y = dir.y, + z = -dir.z + }, true, railtype) + if cur then + return cur + end + end + + return {x=0, y=0, z=0} +end + +function carts:pathfinder(pos_, old_pos, old_dir, distance, ctrl, + pf_switch, railtype) + + local pos = vector.round(pos_) + if vector.equals(old_pos, pos) then + return + end + + local pf_pos = vector.round(old_pos) + local pf_dir = vector.new(old_dir) + distance = math.min(carts.path_distance_max, + math.floor(distance + 1)) + + for i = 1, distance do + pf_dir, pf_switch = self:get_rail_direction( + pf_pos, pf_dir, ctrl, pf_switch or 0, railtype) + + if vector.equals(pf_dir, {x=0, y=0, z=0}) then + -- No way forwards + return pf_pos, pf_dir + end + + pf_pos = vector.add(pf_pos, pf_dir) + + if vector.equals(pf_pos, pos) then + -- Success! Cart moved on correctly + return + end + end + -- Not found. Put cart to predicted position + return pf_pos, pf_dir +end + +function carts:register_rail(name, def_overwrite, railparams) + local def = { + drawtype = "raillike", + paramtype = "light", + sunlight_propagates = true, + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, + }, + sounds = default.node_sound_metal_defaults() + } + for k, v in pairs(def_overwrite) do + def[k] = v + end + if not def.inventory_image then + def.wield_image = def.tiles[1] + def.inventory_image = def.tiles[1] + end + + if railparams then + carts.railparams[name] = table.copy(railparams) + end + + minetest.register_node(name, def) +end + +function carts:get_rail_groups(additional_groups) + -- Get the default rail groups and add more when a table is given + local groups = { + dig_immediate = 2, + attached_node = 1, + rail = 1, + connect_to_raillike = minetest.raillike_group("rail") + } + if type(additional_groups) == "table" then + for k, v in pairs(additional_groups) do + groups[k] = v + end + end + return groups +end diff --git a/mods/carts/init.lua b/mods/carts/init.lua new file mode 100644 index 0000000..fe45303 --- /dev/null +++ b/mods/carts/init.lua @@ -0,0 +1,16 @@ + +carts = {} +carts.modpath = minetest.get_modpath("carts") +carts.railparams = {} + +-- Maximal speed of the cart in m/s (min = -1) +carts.speed_max = 7 +-- Set to -1 to disable punching the cart from inside (min = -1) +carts.punch_speed_max = 5 +-- Maximal distance for the path correction (for dtime peaks) +carts.path_distance_max = 3 + + +dofile(carts.modpath.."/functions.lua") +dofile(carts.modpath.."/rails.lua") +dofile(carts.modpath.."/cart_entity.lua") diff --git a/mods/carts/license.txt b/mods/carts/license.txt new file mode 100644 index 0000000..6c5beb4 --- /dev/null +++ b/mods/carts/license.txt @@ -0,0 +1,54 @@ + +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 SmallJoker +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media +----------------- + +CC-0, see: https://creativecommons.org/share-your-work/public-domain/cc0/, except +if other license is mentioned. + + +Authors +--------- +Originally from PixelBOX (Gambit): + carts_cart_side.png + carts_cart_top.png + carts_cart_front.png* + carts_cart.png* + +sofar + stujones11: + carts_cart.b3d and carts_cart.blend + +hexafraction, modified by sofar + carts_rail_*.png + +http://www.freesound.org/people/YleArkisto/sounds/253159/ - YleArkisto - CC-BY-3.0 + carts_cart_moving.*.ogg diff --git a/mods/carts/models/carts_cart.b3d b/mods/carts/models/carts_cart.b3d new file mode 100644 index 0000000..4e7eba3 Binary files /dev/null and b/mods/carts/models/carts_cart.b3d differ diff --git a/mods/carts/models/carts_cart.blend b/mods/carts/models/carts_cart.blend new file mode 100644 index 0000000..7d2515e Binary files /dev/null and b/mods/carts/models/carts_cart.blend differ diff --git a/mods/carts/rails.lua b/mods/carts/rails.lua new file mode 100644 index 0000000..a5fff8a --- /dev/null +++ b/mods/carts/rails.lua @@ -0,0 +1,59 @@ +carts:register_rail("carts:rail", { + description = "Rail", + tiles = { + "carts_rail_straight.png", "carts_rail_curved.png", + "carts_rail_t_junction.png", "carts_rail_crossing.png" + }, + inventory_image = "carts_rail_straight.png", + wield_image = "carts_rail_straight.png", + groups = carts:get_rail_groups(), +}, {}) + +minetest.register_craft({ + output = "carts:rail 18", + recipe = { + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "group:wood", "default:steel_ingot"}, + } +}) + +minetest.register_alias("default:rail", "carts:rail") + + +carts:register_rail("carts:powerrail", { + description = "Powered Rail", + tiles = { + "carts_rail_straight_pwr.png", "carts_rail_curved_pwr.png", + "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png" + }, + groups = carts:get_rail_groups(), +}, {acceleration = 5}) + +minetest.register_craft({ + output = "carts:powerrail 18", + recipe = { + {"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"}, + } +}) + + +carts:register_rail("carts:brakerail", { + description = "Brake Rail", + tiles = { + "carts_rail_straight_brk.png", "carts_rail_curved_brk.png", + "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png" + }, + groups = carts:get_rail_groups(), +}, {acceleration = -3}) + +minetest.register_craft({ + 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:wood", "default:steel_ingot"}, + } +}) diff --git a/mods/carts/sounds/carts_cart_moving.1.ogg b/mods/carts/sounds/carts_cart_moving.1.ogg new file mode 100644 index 0000000..869e765 Binary files /dev/null and b/mods/carts/sounds/carts_cart_moving.1.ogg differ diff --git a/mods/carts/sounds/carts_cart_moving.2.ogg b/mods/carts/sounds/carts_cart_moving.2.ogg new file mode 100644 index 0000000..b4cc508 Binary files /dev/null and b/mods/carts/sounds/carts_cart_moving.2.ogg differ diff --git a/mods/carts/sounds/carts_cart_moving.3.ogg b/mods/carts/sounds/carts_cart_moving.3.ogg new file mode 100644 index 0000000..e19a782 Binary files /dev/null and b/mods/carts/sounds/carts_cart_moving.3.ogg differ diff --git a/mods/carts/textures/carts_cart.png b/mods/carts/textures/carts_cart.png new file mode 100644 index 0000000..965347c Binary files /dev/null and b/mods/carts/textures/carts_cart.png differ diff --git a/mods/carts/textures/carts_cart_front.png b/mods/carts/textures/carts_cart_front.png new file mode 100644 index 0000000..38955b2 Binary files /dev/null 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 new file mode 100644 index 0000000..f53808c Binary files /dev/null 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 new file mode 100644 index 0000000..d9a31a9 Binary files /dev/null and b/mods/carts/textures/carts_cart_top.png differ diff --git a/mods/carts/textures/carts_rail_crossing.png b/mods/carts/textures/carts_rail_crossing.png new file mode 100644 index 0000000..e10f3b1 Binary files /dev/null and b/mods/carts/textures/carts_rail_crossing.png differ diff --git a/mods/carts/textures/carts_rail_crossing_brk.png b/mods/carts/textures/carts_rail_crossing_brk.png new file mode 100644 index 0000000..0bf455e Binary files /dev/null and b/mods/carts/textures/carts_rail_crossing_brk.png differ diff --git a/mods/carts/textures/carts_rail_crossing_pwr.png b/mods/carts/textures/carts_rail_crossing_pwr.png new file mode 100644 index 0000000..d763d50 Binary files /dev/null and b/mods/carts/textures/carts_rail_crossing_pwr.png differ diff --git a/mods/carts/textures/carts_rail_curved.png b/mods/carts/textures/carts_rail_curved.png new file mode 100644 index 0000000..b320f0d Binary files /dev/null and b/mods/carts/textures/carts_rail_curved.png differ diff --git a/mods/carts/textures/carts_rail_curved_brk.png b/mods/carts/textures/carts_rail_curved_brk.png new file mode 100644 index 0000000..ca40723 Binary files /dev/null and b/mods/carts/textures/carts_rail_curved_brk.png differ diff --git a/mods/carts/textures/carts_rail_curved_pwr.png b/mods/carts/textures/carts_rail_curved_pwr.png new file mode 100644 index 0000000..781bbd0 Binary files /dev/null and b/mods/carts/textures/carts_rail_curved_pwr.png differ diff --git a/mods/carts/textures/carts_rail_straight.png b/mods/carts/textures/carts_rail_straight.png new file mode 100644 index 0000000..30dcafe Binary files /dev/null and b/mods/carts/textures/carts_rail_straight.png differ diff --git a/mods/carts/textures/carts_rail_straight_brk.png b/mods/carts/textures/carts_rail_straight_brk.png new file mode 100644 index 0000000..0c69052 Binary files /dev/null and b/mods/carts/textures/carts_rail_straight_brk.png differ diff --git a/mods/carts/textures/carts_rail_straight_pwr.png b/mods/carts/textures/carts_rail_straight_pwr.png new file mode 100644 index 0000000..e067ff1 Binary files /dev/null and b/mods/carts/textures/carts_rail_straight_pwr.png differ diff --git a/mods/carts/textures/carts_rail_t_junction.png b/mods/carts/textures/carts_rail_t_junction.png new file mode 100644 index 0000000..8b1b946 Binary files /dev/null and b/mods/carts/textures/carts_rail_t_junction.png differ diff --git a/mods/carts/textures/carts_rail_t_junction_brk.png b/mods/carts/textures/carts_rail_t_junction_brk.png new file mode 100644 index 0000000..6b4f6fa Binary files /dev/null and b/mods/carts/textures/carts_rail_t_junction_brk.png differ diff --git a/mods/carts/textures/carts_rail_t_junction_pwr.png b/mods/carts/textures/carts_rail_t_junction_pwr.png new file mode 100644 index 0000000..dd0eede Binary files /dev/null and b/mods/carts/textures/carts_rail_t_junction_pwr.png differ diff --git a/mods/clothing/LICENSE.txt b/mods/clothing/LICENSE.txt new file mode 100644 index 0000000..f5ff22a --- /dev/null +++ b/mods/clothing/LICENSE.txt @@ -0,0 +1,9 @@ +Clothing - Visible Player Clothing +================================== + +Source Code: Stuart Jones - LGPL v2.1 + +Wool Textures: Based on minetest_game wool - CC BY-SA 3.0 + +Other Textures: Stuart Jones - CC-BY-SA 3.0 + diff --git a/mods/clothing/README.txt b/mods/clothing/README.txt new file mode 100644 index 0000000..1b64966 --- /dev/null +++ b/mods/clothing/README.txt @@ -0,0 +1,31 @@ +Wool Clothing - Wool Clothing [WIP] [clothing] +============================================== + +Depends: multiskin + +Recommends: sfinv, inventory_plus or unified_inventory (use only one) + +Adds simple clothing that can be crafted from coloured wool using a loom. +Requires the wool mod for craft registration. + +Crafting +-------- + +S = [group:stick] +W = [default:pinewood] + ++---+---+---+ +| S | W | S | ++---+---+---+ +| S | W | S | ++---+---+---+ +| W | W | W | ++---+---+---+ + +Output = [clothing:loom] + +Configuration +------------- + +Craft registration can disabled by adding `clothing_enable_craft = false` to +your minetest.conf file. diff --git a/mods/clothing/api.lua b/mods/clothing/api.lua new file mode 100644 index 0000000..611988f --- /dev/null +++ b/mods/clothing/api.lua @@ -0,0 +1,97 @@ +clothing = { + formspec = "size[8,8.5]".. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[current_player;main;0,4.7;8,1;]" .. + "list[current_player;main;0,5.85;8,3;8]" .. + default.get_hotbar_bg(0, 4.7), + registered_callbacks = { + on_update = {}, + on_equip = {}, + on_unequip = {}, + }, + player_textures = {}, +} + +-- CLothing callbacks + +clothing.register_on_update = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_update, func) + end +end + +clothing.register_on_equip = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_equip, func) + end +end + +clothing.register_on_unequip = function(self, func) + if type(func) == "function" then + table.insert(self.registered_callbacks.on_unequip, func) + end +end + +clothing.run_callbacks = function(self, callback, player, index, stack) + if stack then + local def = stack:get_definition() or {} + if type(def[callback]) == "function" then + def[callback](player, index, stack) + end + end + local callbacks = self.registered_callbacks[callback] + if callbacks then + for _, func in pairs(callbacks) do + func(player, index, stack) + end + end +end + +clothing.set_player_clothing = function(self, player) + if not player then + return + end + local name = player:get_player_name() + local clothing_inv = minetest.get_inventory({type = "detached", + name = name .. "_clothing"}) + --local player_inv = player:get_inventory() + if not name or not clothing_inv then + return + end + local layer = { + clothing = {}, + cape = {}, + } + local capes = {} + for i = 1, 6 do + local stack = clothing_inv:get_stack("clothing", i) + local item = stack:get_name() + if stack:get_count() == 1 then + local def = stack:get_definition() + if def.uv_image then + if def.groups.clothing == 1 then + table.insert(layer.clothing, def.uv_image) + elseif def.groups.cape == 1 then + table.insert(layer.cape, def.uv_image) + end + end + end + end + local clothing_out = table.concat(layer.clothing, "^") + local cape_out = table.concat(layer.cape, "^") + if clothing_out == "" then + clothing_out = "blank.png" + end + if cape_out == "" then + cape_out = "blank.png" + end + local skin = multiskin.skins[name] + if skin then + skin.clothing = clothing_out + skin.cape = cape_out + multiskin.update_player_visuals(player) + end + self:run_callbacks("on_update", player) +end diff --git a/mods/clothing/depends.txt b/mods/clothing/depends.txt new file mode 100644 index 0000000..4ceef2b --- /dev/null +++ b/mods/clothing/depends.txt @@ -0,0 +1,6 @@ +multiskin +sfinv? +creative? +inventory_plus? +unified_inventory? +wool? diff --git a/mods/clothing/init.lua b/mods/clothing/init.lua new file mode 100644 index 0000000..ef9c88d --- /dev/null +++ b/mods/clothing/init.lua @@ -0,0 +1,228 @@ +local modpath = minetest.get_modpath(minetest.get_current_modname()) + +dofile(modpath.."/api.lua") +dofile(modpath.."/loom.lua") +local function is_clothing(item) + return minetest.get_item_group(item, "clothing") > 0 or + minetest.get_item_group(item, "cape") > 0 +end + +local function save_clothing_metadata(player, clothing_inv) + local player_inv = player:get_inventory() + local is_empty = true + local clothes = {} + for i = 1, 6 do + local stack = clothing_inv:get_stack("clothing", i) + -- Move all non-clothes back to the player inventory + if not stack:is_empty() and not is_clothing(stack:get_name()) then + player_inv:add_item("main", + clothing_inv:remove_item("clothing", stack)) + stack:clear() + end + if not stack:is_empty() then + clothes[i] = stack:to_string() + is_empty = false + end + end + if is_empty then + player:get_meta():set_string("clothing:inventory", nil) + else + player:get_meta():set_string("clothing:inventory", + minetest.serialize(clothes)) + end +end +local function load_clothing_metadata(player, clothing_inv) + local player_inv = player:get_inventory() + local clothing_meta = player:get_meta():get_string("clothing:inventory") + local clothes = clothing_meta and minetest.deserialize(clothing_meta) or {} + local dirty_meta = false + if not clothing_meta then + -- Backwards compatiblity + for i = 1, 6 do + local stack = player_inv:get_stack("clothing", i) + if not stack:is_empty() then + clothes[i] = stack:to_string() + dirty_meta = true + end + end + end + -- Fill detached slots + clothing_inv:set_size("clothing", 6) + for i = 1, 6 do + clothing_inv:set_stack("clothing", i, clothes[i] or "") + end + + if dirty_meta then + -- Requires detached inventory to be set up + save_clothing_metadata(player, clothing_inv) + end + + -- Clean up deprecated garbage after saving + player_inv:set_size("clothing", 0) +end + +local colors = { + white = "FFFFFF", + grey = "C0C0C0", + black = "121212", + red = "DD0000", + yellow = "FFEE00", + green = "32CD32", + cyan = "00959D", + blue = "003376", + magenta = "D80481", + orange = "E0601A", + violet = "480080", + brown = "391A00", + pink = "FFA5A5", + dark_grey = "696969", + dark_green = "154F00", +} +local function clothing_on_use(itemstack, user, pointed_thing) + local name = user:get_player_name() + local inv = minetest.get_inventory({type = "detached", + name = name .. "_clothing"}) + local list = inv:get_list("clothing") + local index = 0 + for i = 1, #list do + if list[i]:get_name() == "" then + inv:set_stack("clothing", i, itemstack) + index = i + break + end + end + if index == 0 then + return itemstack + end + save_clothing_metadata(user, inv) + clothing:run_callbacks("on_equip", user, index, itemstack) + clothing:set_player_clothing(user) + return "" +end +for color, hex in pairs(colors) do + local desc = color:gsub("%a", string.upper, 1) + desc = desc:gsub("_", " ") + minetest.register_craftitem("clothing:hat_" .. color, { + description = desc.." Cotton Hat", + inventory_image = "clothing_inv_hat.png^[multiply:#" .. hex, + uv_image = "(clothing_uv_hat.png^[multiply:#" .. hex .. ")", + groups = {clothing = 1}, + on_use = clothing_on_use, + }) + minetest.register_craftitem("clothing:shirt_"..color, { + description = desc.." Cotton Shirt", + inventory_image = "clothing_inv_shirt.png^[multiply:#"..hex, + uv_image = "(clothing_uv_shirt.png^[multiply:#"..hex..")", + groups = {clothing=1}, + on_use = clothing_on_use, + }) + minetest.register_craftitem("clothing:pants_"..color, { + description = desc.." Cotton Pants", + inventory_image = "clothing_inv_pants.png^[multiply:#"..hex, + uv_image = "(clothing_uv_pants.png^[multiply:#"..hex..")", + groups = {clothing=1}, + on_use = clothing_on_use, + }) + minetest.register_craftitem("clothing:cape_"..color, { + description = desc.." Cotton Cape", + inventory_image = "clothing_inv_cape.png^[multiply:#"..hex, + uv_image = "(clothing_uv_cape.png^[multiply:#"..hex..")", + groups = {cape=1}, + on_use = clothing_on_use, + }) +end +-- Inventory mod support +--[[ +if minetest.get_modpath("inventory_plus") then + clothing.inv_mod = "inventory_plus" + clothing.formspec = clothing.formspec.. + "button[6,0;2,0.5;main;Back]" +elseif minetest.get_modpath("unified_inventory") and + not unified_inventory.sfinv_compat_layer then + clothing.inv_mod = "unified_inventory" + unified_inventory.register_button("clothing", { + type = "image", + image = "inventory_plus_clothing.png", + }) + unified_inventory.register_page("clothing", { + get_formspec = function(player, perplayer_formspec) + local fy = perplayer_formspec.formspec_y + local name = player:get_player_name() + local formspec = "background[0.06,"..fy.. + ";7.92,7.52;clothing_ui_form.png]".. + "label[0,0;Clothing]".. + "list[detached:"..name.."_clothing;clothing;0,"..fy..";2,3;]".. + "listring[current_player;main]".. + "listring[detached:"..name.."_clothing;clothing]" + return {formspec=formspec} + end, + }) +elseif minetest.get_modpath("sfinv") then + clothing.inv_mod = "sfinv" + sfinv.register_page("clothing:clothing", { + title = "Clothing", + get = function(self, player, context) + local name = player:get_player_name() + local formspec = clothing.formspec.. + "list[detached:"..name.."_clothing;clothing;0,0.5;2,3;]".. + "listring[current_player;main]".. + "listring[detached:"..name.."_clothing;clothing]" + return sfinv.make_formspec(player, context, + formspec, false) + end + }) +end +--]] +--[[ +minetest.register_on_player_receive_fields(function(player, formname, fields) + local name = player:get_player_name() + if clothing.inv_mod == "inventory_plus" and fields.clothing then + inventory_plus.set_inventory_formspec(player, clothing.formspec.. + "list[detached:"..name.."_clothing;clothing;0,0.5;2,3;]".. + "listring[current_player;main]".. + "listring[detached:"..name.."_clothing;clothing]") + end +end) +--]] +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + --local player_inv = player:get_inventory() + local clothing_inv = minetest.create_detached_inventory(name .. "_clothing", { + on_put = function(inv, listname, index, stack, player) + save_clothing_metadata(player, inv) + clothing:run_callbacks("on_equip", player, index, stack) + clothing:set_player_clothing(player) + end, + on_take = function(inv, listname, index, stack, player) + save_clothing_metadata(player, inv) + clothing:run_callbacks("on_unequip", player, index, stack) + clothing:set_player_clothing(player) + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + save_clothing_metadata(player, inv) + clothing:set_player_clothing(player) + end, + allow_put = function(inv, listname, index, stack, player) + local item = stack:get_name() + if is_clothing(item) then + return 1 + end + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + return stack:get_count() + end, + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return count + end, + }, name) + if clothing.inv_mod == "inventory_plus" then + inventory_plus.register_button(player,"clothing", "Clothing") + end + + load_clothing_metadata(player, clothing_inv) + minetest.after(3, function(name) -- TODO FIXME Doesn't apply if executes too soon. + -- Ensure the ObjectRef is valid after 1s + clothing:set_player_clothing(minetest.get_player_by_name(name)) + end, name) +end) diff --git a/mods/clothing/loom.lua b/mods/clothing/loom.lua new file mode 100644 index 0000000..a60f572 --- /dev/null +++ b/mods/clothing/loom.lua @@ -0,0 +1,155 @@ +-- formspec = Wardrobe, simple, to apply clothing/capes. +-- Click "craft" or "loom" to make new clothes. + +minetest.register_node("clothing:loom", { + description = "Loom", + tiles = { + "clothing_loom_top.png", + "clothing_loom_bottom.png", + "clothing_loom_side2.png", + "clothing_loom_side1.png", + "clothing_loom_front.png", + "clothing_loom_front.png", + }, + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + groups = {choppy=2, oddly_breakable_by_hand=1}, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.125, -0.375, 0.5, 0.1875}, -- NodeBox1 + {0.375, -0.5, -0.125, 0.5, 0.5, 0.1875}, -- NodeBox3 + {-0.375, -0.5, -0.5, 0.375, -0.4375, 0.5}, -- NodeBox4 + {-0.5, 0, -0.125, 0.5, 0.0625, 0.1875}, -- NodeBox5 + {-0.5, 0.3125, 0.1875, 0.5, 0.5, 0.25}, -- NodeBox6 + {-0.5, 0.3125, -0.1875, 0.5, 0.5, -0.125}, -- NodeBox7 + {-0.375, -0.1875, -0.5, -0.3125, -0.125, 0.5}, -- NodeBox8 + {0.3125, -0.1875, -0.5, 0.375, -0.125, 0.5}, -- NodeBox9 + {-0.4375, -0.1875, -0.5, 0.4375, -0.125, -0.4375}, -- NodeBox10 + {-0.4375, -0.1875, 0.4375, 0.4375, -0.125, 0.5}, -- NodeBox11 + {-0.375, -0.5, 0.375, -0.3125, -0.125, 0.4375}, -- NodeBox12 + {0.3125, -0.5, 0.375, 0.375, -0.125, 0.4375}, -- NodeBox13 + {-0.375, -0.5, -0.4375, -0.3125, -0.125, -0.375}, -- NodeBox14 + {0.3125, -0.5, -0.4375, 0.375, -0.125, -0.375}, -- NodeBox15 + {-0.3125, -0.4375, -0.25, 0.3125, 0, 0.25}, -- NodeBox16 + } + }, + selection_box = { + type = "fixed", + fixed = { + {-0.5,-0.5,-0.5,0.5,0.5,0.5} + }, + }, + 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", "Loom (owned by " .. (placer:get_player_name() or "") .. ")") + end, + can_dig = function(pos,player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if not inv:is_empty("input") or not inv:is_empty("output") then + return false + end + return true + end, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", + "size[8,8.5;]" .. + jas0.exit_button() .. + "button_exit[0,0;2,1;wardrobe;Wardrobe]" .. + "label[0,1.5;Input Wool]" .. + "list[current_name;input;0,2;1,1;]" .. + "label[7,1.5;Output]" .. + "list[current_name;output;7,2;1,1;]" .. + "label[3,1.25;Hat]" .. + "item_image_button[3,1.75;1,1;clothing:hat_grey;hat; ]" .. + "label[4,1.25;Shirt]" .. + "item_image_button[4,1.75;1,1;clothing:shirt_grey;shirt; ]" .. + "label[3,2.75;Pants]" .. + "item_image_button[3,3.2;1,1;clothing:pants_grey;pants; ]" .. + "label[4,2.75;Cape]" .. + "item_image_button[4,3.2;1,1;clothing:cape_grey;cape; ]" .. + "list[current_player;main;0,4.667;8,1;]" .. + "list[current_player;main;0,5.75;8,3;8]" .. + "listring[current_player;main]" .. + "listring[current_name;input]" .. + "listring[current_player;main]" .. + "listring[current_name;output]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 4.667) .. + "") + meta:set_string("infotext", "Loom") + local inv = meta:get_inventory() + inv:set_size("input", 1) + inv:set_size("output", 1) + end, + on_receive_fields = function(pos, formname, fields, sender) + if fields.wardrobe then + return minetest.after(0.1, function() + local name = sender:get_player_name() + minetest.show_formspec(name, + "clothing:wardrobe", + "size[8,5.25]" .. + jas0.exit_button() .. + "list[detached:" .. name .. "_clothing;clothing;1,0;6,1]" .. + "list[current_player;main;0,1.34;8,1]" .. + "list[current_player;main;0,2.5;8,3;8]" .. + "listring[detached:" .. name .. "_clothing;clothing]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 1.34) .. + "") + end) + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:is_empty("input") then + return + end + local output = nil + local qty = nil + + if fields["hat"] then + output = "clothing:hat_" + qty = "1" + elseif fields["shirt"] then + output = "clothing:shirt_" + qty = "1" + elseif fields["pants"] then + output = "clothing:pants_" + qty = "1" + elseif fields["cape"] then + output = "clothing:cape_" + qty = "1" + end + + if output and qty then + local inputstack = inv:get_stack("input", 1) + local outputstack = inv:get_stack("output", 1) + local woolcol = inputstack:get_name() + if woolcol then + local color = woolcol:gsub("wool:", "") + local stack = output..color.." "..qty + if minetest.registered_items[output..color] and + inv:room_for_item("output", stack) then + inv:add_item("output", stack) + inputstack:take_item() + inv:set_stack("input", 1, inputstack) + end + end + end + end, +}) + +--Craft + +minetest.register_craft({ + output = 'clothing:loom', + recipe = { + {'group:stick', 'default:pinewood', 'group:stick'}, + {'group:stick', 'default:pinewood', 'group:stick'}, + {'default:pinewood', "default:pinewood", 'default:pinewood'}, + }, +}) diff --git a/mods/clothing/textures/clothing_inv_cape.png b/mods/clothing/textures/clothing_inv_cape.png new file mode 100644 index 0000000..b945835 Binary files /dev/null and b/mods/clothing/textures/clothing_inv_cape.png differ diff --git a/mods/clothing/textures/clothing_inv_hat.png b/mods/clothing/textures/clothing_inv_hat.png new file mode 100644 index 0000000..f20a866 Binary files /dev/null and b/mods/clothing/textures/clothing_inv_hat.png differ diff --git a/mods/clothing/textures/clothing_inv_pants.png b/mods/clothing/textures/clothing_inv_pants.png new file mode 100644 index 0000000..b34d7df Binary files /dev/null and b/mods/clothing/textures/clothing_inv_pants.png differ diff --git a/mods/clothing/textures/clothing_inv_shirt.png b/mods/clothing/textures/clothing_inv_shirt.png new file mode 100644 index 0000000..b4ab387 Binary files /dev/null and b/mods/clothing/textures/clothing_inv_shirt.png differ diff --git a/mods/clothing/textures/clothing_loom_background.png b/mods/clothing/textures/clothing_loom_background.png new file mode 100644 index 0000000..55e2411 Binary files /dev/null and b/mods/clothing/textures/clothing_loom_background.png differ diff --git a/mods/clothing/textures/clothing_loom_bottom.png b/mods/clothing/textures/clothing_loom_bottom.png new file mode 100644 index 0000000..228ce9b Binary files /dev/null and b/mods/clothing/textures/clothing_loom_bottom.png differ diff --git a/mods/clothing/textures/clothing_loom_front.png b/mods/clothing/textures/clothing_loom_front.png new file mode 100644 index 0000000..b192a10 Binary files /dev/null and b/mods/clothing/textures/clothing_loom_front.png differ diff --git a/mods/clothing/textures/clothing_loom_side1.png b/mods/clothing/textures/clothing_loom_side1.png new file mode 100644 index 0000000..b81a5ea Binary files /dev/null and b/mods/clothing/textures/clothing_loom_side1.png differ diff --git a/mods/clothing/textures/clothing_loom_side2.png b/mods/clothing/textures/clothing_loom_side2.png new file mode 100644 index 0000000..af220b1 Binary files /dev/null and b/mods/clothing/textures/clothing_loom_side2.png differ diff --git a/mods/clothing/textures/clothing_loom_top.png b/mods/clothing/textures/clothing_loom_top.png new file mode 100644 index 0000000..9b19262 Binary files /dev/null and b/mods/clothing/textures/clothing_loom_top.png differ diff --git a/mods/clothing/textures/clothing_ui_form.png b/mods/clothing/textures/clothing_ui_form.png new file mode 100644 index 0000000..ec27d83 Binary files /dev/null and b/mods/clothing/textures/clothing_ui_form.png differ diff --git a/mods/clothing/textures/clothing_uv_cape.png b/mods/clothing/textures/clothing_uv_cape.png new file mode 100644 index 0000000..f5e44d0 Binary files /dev/null and b/mods/clothing/textures/clothing_uv_cape.png differ diff --git a/mods/clothing/textures/clothing_uv_hat.png b/mods/clothing/textures/clothing_uv_hat.png new file mode 100644 index 0000000..35e66e0 Binary files /dev/null and b/mods/clothing/textures/clothing_uv_hat.png differ diff --git a/mods/clothing/textures/clothing_uv_pants.png b/mods/clothing/textures/clothing_uv_pants.png new file mode 100644 index 0000000..0cf98f2 Binary files /dev/null and b/mods/clothing/textures/clothing_uv_pants.png differ diff --git a/mods/clothing/textures/clothing_uv_shirt.png b/mods/clothing/textures/clothing_uv_shirt.png new file mode 100644 index 0000000..23d63e6 Binary files /dev/null and b/mods/clothing/textures/clothing_uv_shirt.png differ diff --git a/mods/clothing/textures/inventory_plus_clothing.png b/mods/clothing/textures/inventory_plus_clothing.png new file mode 100644 index 0000000..35013f1 Binary files /dev/null and b/mods/clothing/textures/inventory_plus_clothing.png differ diff --git a/mods/craftguide/LICENSE b/mods/craftguide/LICENSE new file mode 100644 index 0000000..1791045 --- /dev/null +++ b/mods/craftguide/LICENSE @@ -0,0 +1,9 @@ +« Copyright © 2015-2017, Jean-Patrick Guerrero + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders X be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software. + +Except as contained in this notice, the name of the shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the . » diff --git a/mods/craftguide/README.md b/mods/craftguide/README.md new file mode 100644 index 0000000..b7d4559 --- /dev/null +++ b/mods/craftguide/README.md @@ -0,0 +1,14 @@ +## ![Preview1](http://i.imgur.com/fIPNYkb.png) Crafting Guide ## + +#### A Crafting Guide for Minetest that doesn't suck. #### + +#### `craftguide` is the most comprehensive mod of its category. #### +#### Consult the [Minetest Wiki](http://wiki.minetest.net/Crafting_guide) for more details and comparisons. #### + +#### This crafting guide is usable with a blue book named *"Crafting Guide"*. #### + +#### This crafting guide features two modes : Standard and Progressive. #### +The Progressive mode is a Terraria-like system that only shows recipes you can craft from items in inventory. +The progressive mode can be enabled with `craftguide_progressive_mode = true` in `minetest.conf`. + +![Preview2](http://i.imgur.com/3q7rVSo.png) diff --git a/mods/craftguide/depends.txt b/mods/craftguide/depends.txt new file mode 100644 index 0000000..368ca56 --- /dev/null +++ b/mods/craftguide/depends.txt @@ -0,0 +1,2 @@ +sfinv_buttons? +intllib? diff --git a/mods/craftguide/description.txt b/mods/craftguide/description.txt new file mode 100644 index 0000000..b5c0540 --- /dev/null +++ b/mods/craftguide/description.txt @@ -0,0 +1,2 @@ +The most comprehensive Crafting Guide +on Minetest. diff --git a/mods/craftguide/init.lua b/mods/craftguide/init.lua new file mode 100644 index 0000000..81ebf0e --- /dev/null +++ b/mods/craftguide/init.lua @@ -0,0 +1,588 @@ +local craftguide, datas, mt = {}, {searches = {}}, minetest +local progressive_mode = mt.settings:get_bool("craftguide_progressive_mode") +local get_recipe, get_recipes = mt.get_craft_recipe, mt.get_all_craft_recipes +local get_result, show_formspec = mt.get_craft_result, mt.show_formspec +local reg_items = mt.registered_items + +craftguide.path = minetest.get_modpath("craftguide") + +-- Intllib +local S = dofile(craftguide.path .. "/intllib.lua") +craftguide.intllib = S + +-- Lua 5.3 removed `table.maxn`, use this alternative in case of breakage: +-- https://github.com/kilbith/xdecor/blob/master/handlers/helpers.lua#L1 +local remove, maxn, sort = table.remove, table.maxn, table.sort +local min, max, floor, ceil = math.min, math.max, math.floor, math.ceil + +local DEFAULT_SIZE = 10 +local MIN_LIMIT, MAX_LIMIT = 9, 12 +DEFAULT_SIZE = min(MAX_LIMIT, max(MIN_LIMIT, DEFAULT_SIZE)) + +local GRID_LIMIT = 5 + +local group_stereotypes = { + wool = "wool:white", + dye = "dye:white", + water_bucket = "bucket:bucket_water", + vessel = "vessels:glass_bottle", + coal = "default:coal_lump", + flower = "flowers:dandelion_yellow", + mesecon_conductor_craftable = "mesecons:wire_00000000_off", +} + +function craftguide:group_to_item(item) + if item:sub(1,6) == "group:" then + local itemsub = item:sub(7) + if group_stereotypes[itemsub] then + item = group_stereotypes[itemsub] + elseif reg_items["default:" .. itemsub] then + item = item:gsub("group:", "default:") + else + for name, def in pairs(reg_items) do + if def.groups[item:match("[^,:]+$")] then + item = name + end + end + end + end + + return item:sub(1,6) == "group:" and "" or item +end + +local function extract_groups(str) + if str:sub(1,6) ~= "group:" then return end + return str:sub(7):split(",") +end + +local function colorize(str) + -- If client <= 0.4.14, don't colorize for compatibility. + return mt.colorize and mt.colorize("#FFFF00", str) or str +end + +local function get_fueltime(item) + return get_result({method = "fuel", width = 1, items = {item}}).time +end + +function craftguide:get_tooltip(item, recipe_type, cooktime, groups) + local tooltip, item_desc = "tooltip[" .. item .. ";", "" + local fueltime = get_fueltime(item) + local has_extras = groups or recipe_type == "cooking" or fueltime > 0 + + if reg_items[item] then + if not groups then + item_desc = reg_items[item].description + end + else + return tooltip .. S("Unknown Item (@1)", item) .. "]" + end + + if groups then + local groupstr = "" + for i = 1, #groups do + groupstr = groupstr .. + colorize(groups[i]) .. (groups[i + 1] and ", " or "") + end + + tooltip = tooltip .. S("Any item belonging to the group(s)") .. ": " .. groupstr + end + + if recipe_type == "cooking" then + tooltip = tooltip .. item_desc .. "\n" + .. S("Cooking time") .. ": " .. colorize(cooktime) + end + + if fueltime > 0 then + tooltip = tooltip .. item_desc .. "\n" + .. S("Burning time") .. ": " .. colorize(fueltime) + end + + return has_extras and tooltip .. "]" or "" +end + +function craftguide:get_recipe(iY, xoffset, tooltip, item, recipe_num, recipes, show_usage) + local formspec, recipes_total = "", #recipes + if recipes_total > 1 then + formspec = formspec .. + "button[0," .. (iY + 3.3) .. ";2,1;alternate;" .. S("Alternate") .. "]" .. + "label[0," .. (iY + 2.8) .. ";" .. + (show_usage and S("Usage") or S("Recipe")) .. " " .. + S("@1 of @2", recipe_num, recipes_total) .. "]" + end + + local recipe_type = recipes[recipe_num].type + local items = recipes[recipe_num].items + local width = recipes[recipe_num].width + + if recipe_type == "cooking" or (recipe_type == "normal" and width == 0) then + local icon = recipe_type == "cooking" and "furnace" or "shapeless" + formspec = formspec .. + "image[" .. (xoffset - 0.8) .. "," .. (iY + 1.7) .. + ";0.5,0.5;craftguide_" .. icon .. ".png]" + end + + if width == 0 then + width = min(3, #items) + end + + local rows = ceil(maxn(items) / width) + + if recipe_type == "normal" and (width > GRID_LIMIT or rows > GRID_LIMIT) then + formspec = formspec .. + "label[" .. xoffset .. "," .. (iY + 2) .. ";" .. + S("Recipe is too big to\nbe displayed (@1x@2)", width, rows) .. "]" + else + local btn_size = 1 + for i, v in pairs(items) do + local X = (i - 1) % width + xoffset + local Y = ceil(i / width + (iY + 2) - min(2, rows)) + + if recipe_type == "normal" and (width > 3 or rows > 3) then + btn_size = width > 3 and 3 / width or 3 / rows + X = btn_size * (i % width) + xoffset + Y = btn_size * floor((i - 1) / width) + (iY + 3) - min(2, rows) + end + + local groups = extract_groups(v) + local label = groups and "\nG" or "" + local item_r = self:group_to_item(v) + local tltip = self:get_tooltip(item_r, recipe_type, width, groups) + + formspec = formspec .. + "item_image_button[" .. X .. "," .. (Y + 0.2) .. ";" .. + btn_size .. "," .. btn_size .. ";" .. item_r .. + ";" .. item_r .. ";" .. label .. "]" .. tltip + end + end + + local output = recipes[recipe_num].output + return formspec .. + "image[" .. (xoffset - 1) .. "," .. (iY + 2.35) .. + ";0.9,0.7;craftguide_arrow.png]" .. + "item_image_button[" .. (xoffset - 2) .. "," .. (iY + 2.2) .. ";1,1;" .. + output .. ";" .. item .. ";]" .. tooltip +end + +function craftguide:get_formspec(player_name, is_fuel) + local data = datas[player_name] + local iY = data.iX - 5 + local ipp = data.iX * iY + + if not data.items then + data.items = datas.init_items + end + + data.pagemax = max(1, ceil(#data.items / ipp)) + + local formspec = "size[" .. (data.iX - 0.35) .. "," .. (iY + 4) .. ";]" .. [[ + background[1,1;1,1;craftguide_bg.png;true] + button[2.4,0.23;0.8,0.5;search;?] + button[3.05,0.23;0.8,0.5;clear;X] + field_close_on_enter[filter;false] + ]] .. + "tooltip[search;" .. S("Search") .. "]" .. + "tooltip[clear;" .. S("Reset") .. "]" .. + "tooltip[size_inc;" .. S("Increase window size") .. "]" .. + "tooltip[size_dec;" .. S("Decrease window size") .. "]" .. + "tooltip[prev;" .. S("Previous page") .. "]" .. + "tooltip[next;" .. S("Next page") .. "]" .. + "button[" .. (data.iX * 0.48) .. ",-0.02;0.7,1;size_inc;+]" .. + "button[" .. ((data.iX * 0.48) + 0.5) .. + ",-0.02;0.7,1;size_dec;-]" .. + "button[" .. (data.iX - 3.1) .. ",0;0.8,0.95;prev;<]" .. + "label[" .. (data.iX - 2.2) .. ",0.18;" .. + colorize(data.pagenum) .. " / " .. data.pagemax .. "]" .. + "button[" .. (data.iX - 1.2) .. ",0;0.8,0.95;next;>]" .. + "field[0.3,0.32;2.5,1;filter;;" .. + mt.formspec_escape(data.filter) .. "]" + + local even_num = data.iX % 2 == 0 + local xoffset = data.iX / 2 + (even_num and 0.5 or 0) + + if not next(data.items) then + formspec = formspec .. + "label[" .. (xoffset - (even_num and 1.5 or 1)) .. ",2;" .. + S("No item to show") .. "]" + end + + local first_item = (data.pagenum - 1) * ipp + for i = first_item, first_item + ipp - 1 do + local name = data.items[i + 1] + if not name then break end + local X = i % data.iX + local Y = (i % ipp - X) / data.iX + 1 + + formspec = formspec .. + "item_image_button[" .. (X - (X * 0.05)) .. "," .. Y .. ";1.1,1.1;" .. + name .. ";" .. name .. "_inv;]" + end + + if data.item and reg_items[data.item] then + local tooltip = self:get_tooltip(data.item) + if not data.recipes_item or (is_fuel and not get_recipe(data.item).items) then + formspec = formspec .. + "image[" .. (xoffset - 1) .. "," .. (iY + 2.35) .. + ";0.9,0.7;craftguide_arrow.png]" .. + "item_image_button[" .. xoffset .. "," .. (iY + 2.2) .. + ";1,1;" .. data.item .. ";" .. data.item .. ";]" .. + tooltip .. + "image[" .. (xoffset - 2) .. "," .. + (iY + 2.18) .. ";1,1;craftguide_fire.png]" + else + local show_usage = data.show_usage + formspec = formspec .. + self:get_recipe(iY, xoffset, tooltip, + data.item, + data.rnum, + (show_usage and data.usages or data.recipes_item), + show_usage) + end + end + + data.formspec = formspec + show_formspec(player_name, "craftguide", formspec) +end + +local function player_has_item(T) + for i = 1, #T do + if T[i] then + return true + end + end +end + +local function group_to_items(group) + local items_with_group, counter = {}, 0 + for name, def in pairs(reg_items) do + if def.groups[group:sub(7)] then + counter = counter + 1 + items_with_group[counter] = name + end + end + + return items_with_group +end + +local function item_in_inv(inv, item) + return inv:contains_item("main", item) +end + +function craftguide:recipe_in_inv(inv, item_name, recipes_f) + local recipes = recipes_f or get_recipes(item_name) or {} + local show_item_recipes = {} + + for i = 1, #recipes do + show_item_recipes[i] = true + for _, item in pairs(recipes[i].items) do + local group_in_inv = false + if item:sub(1,6) == "group:" then + local groups = group_to_items(item) + for j = 1, #groups do + if item_in_inv(inv, groups[j]) then + group_in_inv = true + end + end + end + if not group_in_inv and not item_in_inv(inv, item) then + show_item_recipes[i] = false + end + end + end + + for i = #show_item_recipes, 1, -1 do + if not show_item_recipes[i] then + remove(recipes, i) + end + end + + return recipes, player_has_item(show_item_recipes) +end + +function craftguide:get_init_items() + local items_list, counter = {}, 0 + for name, def in pairs(reg_items) do + local is_fuel = get_fueltime(name) > 0 + if (not (def.groups.not_in_craft_guide == 1 or def.groups.not_in_creative_inventory == 1)) and + (get_recipe(name).items or is_fuel) and + def.description and def.description ~= "" then + + counter = counter + 1 + items_list[counter] = name + end + end + + sort(items_list) + datas.init_items = items_list +end + +function craftguide:get_filter_items(data, player) + local filter = data.filter + if datas.searches[filter] then + data.items = datas.searches[filter] + return + end + + local items_list = progressive_mode and data.init_filter_items or datas.init_items + local inv = player:get_inventory() + local filtered_list, counter = {}, 0 + + for i = 1, #items_list do + local item = items_list[i] + local item_desc = reg_items[item].description:lower() + + if filter ~= "" then + if item:find(filter, 1, true) or item_desc:find(filter, 1, true) then + counter = counter + 1 + filtered_list[counter] = item + end + elseif progressive_mode then + local _, has_item = self:recipe_in_inv(inv, item) + if has_item then + counter = counter + 1 + filtered_list[counter] = item + end + end + end + + if progressive_mode then + if not data.items then + data.init_filter_items = filtered_list + end + elseif filter ~= "" then + -- Cache the results only if searched 2 times + if datas.searches[filter] == nil then + datas.searches[filter] = false + else + datas.searches[filter] = filtered_list + end + end + + data.items = filtered_list +end + +function craftguide:get_item_usages(item) + local usages = {} + for name, def in pairs(reg_items) do + if not (def.groups.not_in_creative_inventory == 1) and + (get_recipe(name).items) and def.description and def.description ~= "" then + local recipes = get_recipes(name) + for i = 1, #recipes do + local recipe = recipes[i] + local items = recipe.items + + for j = 1, #items do + if items[j] == item then + usages[#usages + 1] = { + type = recipe.type, + items = items, + width = recipe.width, + output = recipe.output, + } + break + end + end + end + end + end + + return usages +end + +mt.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "craftguide" then return end + local player_name = player:get_player_name() + local data = datas[player_name] + + if fields.clear then + data.show_usage = nil + data.filter = "" + data.item = nil + data.pagenum = 1 + data.rnum = 1 + + data.items = progressive_mode and data.init_filter_items or datas.init_items + craftguide:get_formspec(player_name) + + elseif fields.alternate then + local num + if data.show_usage then + num = data.usages[data.rnum + 1] + else + num = data.recipes_item[data.rnum + 1] + end + + data.rnum = num and data.rnum + 1 or 1 + craftguide:get_formspec(player_name) + + elseif (fields.key_enter_field == "filter" or fields.search) and + fields.filter ~= "" then + data.filter = fields.filter:lower() + data.pagenum = 1 + craftguide:get_filter_items(data, player) + craftguide:get_formspec(player_name) + + elseif fields.prev or fields.next then + data.pagenum = data.pagenum - (fields.prev and 1 or -1) + + if data.pagenum > data.pagemax then + data.pagenum = 1 + elseif data.pagenum == 0 then + data.pagenum = data.pagemax + end + + craftguide:get_formspec(player_name) + + elseif (fields.size_inc and data.iX < MAX_LIMIT) or + (fields.size_dec and data.iX > MIN_LIMIT) then + data.pagenum = 1 + data.iX = data.iX - (fields.size_dec and 1 or -1) + craftguide:get_formspec(player_name) + + else for item in pairs(fields) do + if item:find(":") then + if item:sub(-4) == "_inv" then + item = item:sub(1,-5) + end + + local is_fuel = get_fueltime(item) > 0 + local recipes = get_recipes(item) + if not recipes and not is_fuel then return end + + if not data.show_usage and item == data.item and not progressive_mode then + data.usages = craftguide:get_item_usages(item) + if next(data.usages) then + data.show_usage = true + data.rnum = 1 + end + + craftguide:get_formspec(player_name) + else + if progressive_mode then + local inv = player:get_inventory() + local _, has_item = craftguide:recipe_in_inv(inv, item) + + if not has_item then return end + recipes = craftguide:recipe_in_inv(inv, item, recipes) + end + + data.item = item + data.recipes_item = recipes + data.rnum = 1 + data.show_usage = nil + + craftguide:get_formspec(player_name, is_fuel) + end + end + end + end +end) + +function craftguide:on_use(itemstack, user) + if not datas.init_items then + self:get_init_items() + end + + local player_name = user:get_player_name() + local data = datas[player_name] + + if progressive_mode or not data then + datas[player_name] = {filter = "", pagenum = 1, iX = DEFAULT_SIZE} + if progressive_mode then + self:get_filter_items(datas[player_name], user) + end + + self:get_formspec(player_name) + else + show_formspec(player_name, "craftguide", data.formspec) + end +end + +mt.register_craftitem("craftguide:book", { + description = S("Crafting Guide"), + inventory_image = "craftguide_book.png", + wield_image = "craftguide_book.png", + stack_max = 1, + groups = {book = 1}, + on_use = function(itemstack, user) + craftguide:on_use(itemstack, user) + end +}) +--[[ +mt.register_node("craftguide:sign", { + description = S("Crafting Guide Sign"), + drawtype = "nodebox", + tiles = {"craftguide_sign.png"}, + inventory_image = "craftguide_sign_inv.png", + wield_image = "craftguide_sign_inv.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + groups = {wood = 1, oddly_breakable_by_hand = 1, flammable = 3}, + node_box = { + type = "wallmounted", + wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125}, + wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}, + wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375} + }, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", S("Crafting Guide Sign")) + end, + on_rightclick = function(pos, node, user, itemstack) + craftguide:on_use(itemstack, user) + end +}) +--]] +mt.register_craft({ + type = "fuel", + recipe = "craftguide:book", + burntime = 3 +}) +--[[ +mt.register_craft({ + output = "craftguide:sign", + type = "shapeless", + recipe = {"default:sign_wall_wood"} +}) + +mt.register_craft({ + type = "fuel", + recipe = "craftguide:sign", + burntime = 10 +}) +--]] +if rawget(_G, "sfinv_buttons") then + sfinv_buttons.register_button("craftguide", { + title = S("Crafting Guide"), + tooltip = S("Shows a list of available crafting recipes, cooking recipes and fuels"), + action = function(player) + craftguide:on_use(nil, player) + end, + image = "craftguide_book.png", + }) +end + +mt.register_alias("xdecor:crafting_guide", "craftguide:book") + +--[[ Custom recipes (>3x3) test code + +mt.register_craftitem("craftguide:custom_recipe_test", { + description = "Custom Recipe Test", +}) + +local cr = {} +for x = 1, 6 do + cr[x] = {} + for i = 1, 10 - x do + cr[x][i] = {} + for j = 1, 10 - x do + cr[x][i][j] = "group:wood" + end + end + + mt.register_craft({ + output = "craftguide:custom_recipe_test", + recipe = cr[x] + }) +end +]] diff --git a/mods/craftguide/intllib.lua b/mods/craftguide/intllib.lua new file mode 100644 index 0000000..6669d72 --- /dev/null +++ b/mods/craftguide/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/mods/craftguide/locale/de.po b/mods/craftguide/locale/de.po new file mode 100644 index 0000000..8e5a8de --- /dev/null +++ b/mods/craftguide/locale/de.po @@ -0,0 +1,90 @@ +# German translation for craftguide mod. +# Copyright (C) 2018 +# This file is distributed under the same license as the craftguide package. +# codexp , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.27\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-23 00:17+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: init.lua +msgid "Unknown Item (@1)" +msgstr "Unbekannter Gegenstand (@1)" + +#: init.lua +msgid "Any item belonging to the group(s)" +msgstr "Beliebiger Gegenstand aus der Gruppe" + +#: init.lua +msgid "Cooking time" +msgstr "Kochzeit" + +#: init.lua +msgid "Burning time" +msgstr "Brennzeit" + +#: init.lua +msgid "Alternate" +msgstr "Andere" + +#: init.lua +msgid "Recipe @1 of @2" +msgstr "Rezept @1 von @2" + +#: init.lua +msgid "" +"Recipe is too big to\n" +"be displayed (@1x@2)" +msgstr "" +"Rezept ist zu groß\n" +"für die Anzeige (@1x@2)" + +#: init.lua +msgid "Search" +msgstr "Suche" + +#: init.lua +msgid "Reset" +msgstr "Zurücksetzen" + +#: init.lua +msgid "Increase window size" +msgstr "Fenster vergrößern" + +#: init.lua +msgid "Decrease window size" +msgstr "Fenster verkleinern" + +#: init.lua +msgid "Previous page" +msgstr "Vorherige Seite" + +#: init.lua +msgid "Next page" +msgstr "Nächste Seite" + +#: init.lua +msgid "No item to show" +msgstr "Nichts anzuzeigen" + +#: init.lua +msgid "Crafting Guide" +msgstr "Rezeptbuch" + +#: init.lua +msgid "Crafting Guide Sign" +msgstr "Rezepttafel" + +#: init.lua +msgid "Shows a list of available crafting recipes, cooking recipes and fuels" +msgstr "Zeigt eine Liste von verfügbaren Rezepten, Kochrezepten und Brennmaterialien" diff --git a/mods/craftguide/locale/ms.po b/mods/craftguide/locale/ms.po new file mode 100644 index 0000000..56a1c20 --- /dev/null +++ b/mods/craftguide/locale/ms.po @@ -0,0 +1,91 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: craftguide\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-23 18:35+0100\n" +"PO-Revision-Date: 2018-04-18 02:02+0800\n" +"Language-Team: muhdnurhidayat \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"Last-Translator: MuhdNurHidayat (MNH48) \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ms\n" + +#: init.lua +msgid "Unknown Item (@1)" +msgstr "Item Tidak Diketahui (@1)" + +#: init.lua +msgid "Any item belonging to the group(s)" +msgstr "Sebarang item dari kumpulan" + +#: init.lua +msgid "Cooking time" +msgstr "Tempoh memasak" + +#: init.lua +msgid "Burning time" +msgstr "Tempoh pembakaran" + +#: init.lua +msgid "Alternate" +msgstr "Resipi lain" + +#: init.lua +msgid "Recipe @1 of @2" +msgstr "Resipi @1 dari @2" + +#: init.lua +msgid "" +"Recipe is too big to\n" +"be displayed (@1x@2)" +msgstr "" +"Resipi terlalu besar\n" +"untuk paparan (@1x@2)" + +#: init.lua +msgid "Search" +msgstr "Cari" + +#: init.lua +msgid "Reset" +msgstr "Set semula" + +#: init.lua +msgid "Increase window size" +msgstr "Besarkan saiz tetingkap" + +#: init.lua +msgid "Decrease window size" +msgstr "Kecilkan saiz tetingkap" + +#: init.lua +msgid "Previous page" +msgstr "Halaman sebelumnya" + +#: init.lua +msgid "Next page" +msgstr "Halaman seterusnya" + +#: init.lua +msgid "No item to show" +msgstr "Tiada item untuk dipaparkan" + +#: init.lua +msgid "Crafting Guide" +msgstr "Panduan Pertukangan" + +#: init.lua +msgid "Crafting Guide Sign" +msgstr "Papan Tanda Panduan Pertukangan" + +#: init.lua +msgid "Shows a list of available crafting recipes, cooking recipes and fuels" +msgstr "Menunjukkan senarai resipi pertukangan, resipi memasak dan bahan api yang ada" diff --git a/mods/craftguide/locale/ru.po b/mods/craftguide/locale/ru.po new file mode 100644 index 0000000..e99d0c6 --- /dev/null +++ b/mods/craftguide/locale/ru.po @@ -0,0 +1,90 @@ +# Russian translation for craftguide mod. +# Copyright (C) 2018 +# This file is distributed under the same license as the craftguide package. +# codexp , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 1.27\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-23 00:17+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: init.lua +msgid "Unknown Item (@1)" +msgstr "Неизвестный элемент (@1)" + +#: init.lua +msgid "Any item belonging to the group(s)" +msgstr "Любой элемент из группы" + +#: init.lua +msgid "Cooking time" +msgstr "Время преготовления" + +#: init.lua +msgid "Burning time" +msgstr "Время горения" + +#: init.lua +msgid "Alternate" +msgstr "Другой" + +#: init.lua +msgid "Recipe @1 of @2" +msgstr "Рецепт @1 из @2" + +#: init.lua +msgid "" +"Recipe is too big to\n" +"be displayed (@1x@2)" +msgstr "" +"Рецепт слишком большой\n" +"для показа (@1x@2)" + +#: init.lua +msgid "Search" +msgstr "Поиск" + +#: init.lua +msgid "Reset" +msgstr "Сброс" + +#: init.lua +msgid "Increase window size" +msgstr "Увеличить окно" + +#: init.lua +msgid "Decrease window size" +msgstr "Уменьшить окно" + +#: init.lua +msgid "Previous page" +msgstr "Предыдущая страница" + +#: init.lua +msgid "Next page" +msgstr "Следущая страница" + +#: init.lua +msgid "No item to show" +msgstr "Нет элемента для показа" + +#: init.lua +msgid "Crafting Guide" +msgstr "книга рецептов крафта" + +#: init.lua +msgid "Crafting Guide Sign" +msgstr "табличка рецептов крафта" + +#: init.lua +msgid "Shows a list of available crafting recipes, cooking recipes and fuels" +msgstr "Показывает список рецептов крафта, преготовления и топливо" diff --git a/mods/craftguide/locale/template.pot b/mods/craftguide/locale/template.pot new file mode 100644 index 0000000..8f8470d --- /dev/null +++ b/mods/craftguide/locale/template.pot @@ -0,0 +1,88 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-03-23 18:35+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: init.lua +msgid "Unknown Item (@1)" +msgstr "" + +#: init.lua +msgid "Any item belonging to the group(s)" +msgstr "" + +#: init.lua +msgid "Cooking time" +msgstr "" + +#: init.lua +msgid "Burning time" +msgstr "" + +#: init.lua +msgid "Alternate" +msgstr "" + +#: init.lua +msgid "Recipe @1 of @2" +msgstr "" + +#: init.lua +msgid "" +"Recipe is too big to\n" +"be displayed (@1x@2)" +msgstr "" + +#: init.lua +msgid "Search" +msgstr "" + +#: init.lua +msgid "Reset" +msgstr "" + +#: init.lua +msgid "Increase window size" +msgstr "" + +#: init.lua +msgid "Decrease window size" +msgstr "" + +#: init.lua +msgid "Previous page" +msgstr "" + +#: init.lua +msgid "Next page" +msgstr "" + +#: init.lua +msgid "No item to show" +msgstr "" + +#: init.lua +msgid "Crafting Guide" +msgstr "" + +#: init.lua +msgid "Crafting Guide Sign" +msgstr "" + +#: init.lua +msgid "Shows a list of available crafting recipes, cooking recipes and fuels" +msgstr "" diff --git a/mods/craftguide/mod.conf b/mods/craftguide/mod.conf new file mode 100644 index 0000000..c32f714 --- /dev/null +++ b/mods/craftguide/mod.conf @@ -0,0 +1 @@ +name = craftguide diff --git a/mods/craftguide/textures/craftguide_arrow.png b/mods/craftguide/textures/craftguide_arrow.png new file mode 100644 index 0000000..e8d3598 Binary files /dev/null and b/mods/craftguide/textures/craftguide_arrow.png differ diff --git a/mods/craftguide/textures/craftguide_bg.png b/mods/craftguide/textures/craftguide_bg.png new file mode 100644 index 0000000..db50299 Binary files /dev/null and b/mods/craftguide/textures/craftguide_bg.png differ diff --git a/mods/craftguide/textures/craftguide_book.png b/mods/craftguide/textures/craftguide_book.png new file mode 100644 index 0000000..e46cd38 Binary files /dev/null and b/mods/craftguide/textures/craftguide_book.png differ diff --git a/mods/craftguide/textures/craftguide_fire.png b/mods/craftguide/textures/craftguide_fire.png new file mode 100644 index 0000000..6e3a832 Binary files /dev/null and b/mods/craftguide/textures/craftguide_fire.png differ diff --git a/mods/craftguide/textures/craftguide_furnace.png b/mods/craftguide/textures/craftguide_furnace.png new file mode 100644 index 0000000..4c12e50 Binary files /dev/null and b/mods/craftguide/textures/craftguide_furnace.png differ diff --git a/mods/craftguide/textures/craftguide_shapeless.png b/mods/craftguide/textures/craftguide_shapeless.png new file mode 100644 index 0000000..179d317 Binary files /dev/null and b/mods/craftguide/textures/craftguide_shapeless.png differ diff --git a/mods/craftguide/textures/craftguide_sign.png b/mods/craftguide/textures/craftguide_sign.png new file mode 100644 index 0000000..f64b5ab Binary files /dev/null and b/mods/craftguide/textures/craftguide_sign.png differ diff --git a/mods/craftguide/textures/craftguide_sign_inv.png b/mods/craftguide/textures/craftguide_sign_inv.png new file mode 100644 index 0000000..6137234 Binary files /dev/null and b/mods/craftguide/textures/craftguide_sign_inv.png differ diff --git a/mods/creative/README.txt b/mods/creative/README.txt new file mode 100644 index 0000000..32e8d22 --- /dev/null +++ b/mods/creative/README.txt @@ -0,0 +1,17 @@ +Minetest Game mod: creative +=========================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Perttu Ahola (celeron55) (MIT) +Jean-Patrick G. (kilbith) (MIT) + +Author of media (textures) +-------------------------- +paramat (CC BY-SA 3.0): +* creative_prev_icon.png +* creative_next_icon.png +* creative_search_icon.png +* creative_clear_icon.png +* creative_trash_icon.png derived from a texture by kilbith (CC BY-SA 3.0) diff --git a/mods/creative/depends.txt b/mods/creative/depends.txt new file mode 100644 index 0000000..975e652 --- /dev/null +++ b/mods/creative/depends.txt @@ -0,0 +1,2 @@ +default +sfinv diff --git a/mods/creative/init.lua b/mods/creative/init.lua new file mode 100644 index 0000000..8a6b9f2 --- /dev/null +++ b/mods/creative/init.lua @@ -0,0 +1,74 @@ +creative = {} + +minetest.register_privilege("creative", { + description = "Allow player to use creative inventory", + give_to_singleplayer = false, + give_to_admin = false +}) + +local creative_mode_cache = minetest.settings:get_bool("creative_mode") + +function creative.is_enabled_for(name) + return creative_mode_cache or + minetest.check_player_privs(name, {creative = true}) +end + +--dofile(minetest.get_modpath("creative") .. "/inventory.lua") + +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. + -- To speed up digging in creative, hand 'maxlevel' and 'digtime' have been + -- increased such that nodes of differing levels have an insignificant + -- effect on digtime. + local digtime = 42 + local caps = {times = {digtime, digtime, digtime}, uses = 0, maxlevel = 256} + + minetest.register_item(":", { + type = "none", + wield_image = "wieldhand.png", + wield_scale = {x = 1, y = 1, z = 2.5}, + range = 10, + tool_capabilities = { + full_punch_interval = 0.5, + max_drop_level = 3, + groupcaps = { + crumbly = caps, + cracky = caps, + snappy = caps, + choppy = caps, + oddly_breakable_by_hand = caps, + }, + damage_groups = {fleshy = 10}, + } + }) +end + +-- Unlimited node placement +--[[ +minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack) + if placer and placer:is_player() then + return creative.is_enabled_for(placer:get_player_name()) + end +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() or + 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 +end +--]] diff --git a/mods/creative/inventory.lua b/mods/creative/inventory.lua new file mode 100644 index 0000000..79a8529 --- /dev/null +++ b/mods/creative/inventory.lua @@ -0,0 +1,193 @@ +local player_inventory = {} +local inventory_cache = {} + +local function init_creative_cache(items) + inventory_cache[items] = {} + local i_cache = inventory_cache[items] + + for name, def in pairs(items) do + if def.groups.not_in_creative_inventory ~= 1 and + def.description and def.description ~= "" then + i_cache[name] = def + end + end + table.sort(i_cache) + return i_cache +end + +function creative.init_creative_inventory(player) + local player_name = player:get_player_name() + player_inventory[player_name] = { + size = 0, + filter = "", + start_i = 0 + } + + minetest.create_detached_inventory("creative_" .. player_name, { + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2) + local name = player2 and player2:get_player_name() or "" + if not creative.is_enabled_for(name) or + to_list == "main" then + return 0 + end + return count + end, + allow_put = function(inv, listname, index, stack, player2) + return 0 + end, + allow_take = function(inv, listname, index, stack, player2) + local name = player2 and player2:get_player_name() or "" + if not creative.is_enabled_for(name) then + return 0 + end + return -1 + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player2) + end, + on_take = function(inv, listname, index, stack, player2) + if stack and stack:get_count() > 0 then + minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory") + end + end, + }, player_name) + + 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 items = inventory_cache[tab_content] or init_creative_cache(tab_content) + + for name, def in pairs(items) do + if def.name:find(inv.filter, 1, true) or + def.description:lower():find(inv.filter, 1, true) then + creative_list[#creative_list+1] = name + end + end + + table.sort(creative_list) + player_inv:set_size("main", #creative_list) + player_inv:set_list("main", creative_list) + inv.size = #creative_list +end + +-- Create the trash field +local trash = minetest.create_detached_inventory("creative_trash", { + -- Allow the stack to be placed and remove it in on_put() + -- This allows the creative inventory to restore the stack + allow_put = function(inv, listname, index, stack, player) + return stack:get_count() + end, + on_put = function(inv, listname) + inv:set_list(listname, {}) + end, +}) +trash:set_size("main", 1) + +creative.formspec_add = "" + +function creative.register_tab(name, title, items) + sfinv.register_page("creative:" .. name, { + title = title, + is_in_nav = function(self, player, context) + return creative.is_enabled_for(player:get_player_name()) + end, + get = function(self, player, context) + local player_name = player:get_player_name() + creative.update_creative_inventory(player_name, items) + local inv = player_inventory[player_name] + local start_i = inv.start_i or 0 + local pagenum = math.floor(start_i / (3*8) + 1) + local pagemax = math.ceil(inv.size / (3*8)) + return sfinv.make_formspec(player, context, + "label[6.2,3.35;" .. minetest.colorize("#FFFF00", tostring(pagenum)) .. " / " .. tostring(pagemax) .. "]" .. + [[ + image[4.06,3.4;0.8,0.8;creative_trash_icon.png] + listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF] + list[current_player;main;0,4.7;8,1;] + list[current_player;main;0,5.85;8,3;8] + list[detached:creative_trash;main;4,3.3;1,1;] + listring[] + image_button[5.4,3.25;0.8,0.8;creative_prev_icon.png;creative_prev;] + image_button[7.2,3.25;0.8,0.8;creative_next_icon.png;creative_next;] + image_button[2.1,3.25;0.8,0.8;creative_search_icon.png;creative_search;] + image_button[2.75,3.25;0.8,0.8;creative_clear_icon.png;creative_clear;] + tooltip[creative_search;Search] + tooltip[creative_clear;Reset] + tooltip[creative_prev;Previous page] + tooltip[creative_next;Next page] + listring[current_player;main] + field_close_on_enter[creative_filter;false] + ]] .. + "field[0.3,3.5;2.2,1;creative_filter;;" .. minetest.formspec_escape(inv.filter) .. "]" .. + "listring[detached:creative_" .. player_name .. ";main]" .. + "list[detached:creative_" .. player_name .. ";main;0,0;8,3;" .. tostring(start_i) .. "]" .. + default.get_hotbar_bg(0,4.7) .. + default.gui_bg .. default.gui_bg_img .. default.gui_slots + .. creative.formspec_add, false) + end, + on_enter = function(self, player, context) + local player_name = player:get_player_name() + local inv = player_inventory[player_name] + if inv then + inv.start_i = 0 + end + end, + on_player_receive_fields = function(self, player, context, fields) + local player_name = player:get_player_name() + local inv = player_inventory[player_name] + assert(inv) + + if fields.creative_clear then + inv.start_i = 0 + inv.filter = "" + creative.update_creative_inventory(player_name, items) + sfinv.set_player_inventory_formspec(player, context) + elseif fields.creative_search or + fields.key_enter_field == "creative_filter" then + inv.start_i = 0 + inv.filter = fields.creative_filter:lower() + creative.update_creative_inventory(player_name, items) + sfinv.set_player_inventory_formspec(player, context) + elseif not fields.quit then + local start_i = inv.start_i or 0 + + if fields.creative_prev then + start_i = start_i - 3*8 + if start_i < 0 then + start_i = inv.size - (inv.size % (3*8)) + if inv.size == start_i then + start_i = math.max(0, inv.size - (3*8)) + end + end + elseif fields.creative_next then + start_i = start_i + 3*8 + if start_i >= inv.size then + start_i = 0 + end + end + + inv.start_i = start_i + sfinv.set_player_inventory_formspec(player, context) + end + end + }) +end + +creative.register_tab("all", "All", minetest.registered_items) +creative.register_tab("nodes", "Nodes", minetest.registered_nodes) +creative.register_tab("tools", "Tools", minetest.registered_tools) +creative.register_tab("craftitems", "Items", minetest.registered_craftitems) + +local old_homepage_name = sfinv.get_homepage_name +function sfinv.get_homepage_name(player) + if creative.is_enabled_for(player:get_player_name()) then + return "creative:all" + else + return old_homepage_name(player) + end +end diff --git a/mods/creative/license.txt b/mods/creative/license.txt new file mode 100644 index 0000000..50ff9c7 --- /dev/null +++ b/mods/creative/license.txt @@ -0,0 +1,61 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) +Copyright (C) 2015-2016 Jean-Patrick G. (kilbith) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2016 Jean-Patrick G. (kilbith) +Copyright (C) 2018 paramat + +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/creative/textures/creative_clear_icon.png b/mods/creative/textures/creative_clear_icon.png new file mode 100644 index 0000000..9244264 Binary files /dev/null and b/mods/creative/textures/creative_clear_icon.png differ diff --git a/mods/creative/textures/creative_next_icon.png b/mods/creative/textures/creative_next_icon.png new file mode 100644 index 0000000..82cf3d3 Binary files /dev/null and b/mods/creative/textures/creative_next_icon.png differ diff --git a/mods/creative/textures/creative_prev_icon.png b/mods/creative/textures/creative_prev_icon.png new file mode 100644 index 0000000..b26cd15 Binary files /dev/null and b/mods/creative/textures/creative_prev_icon.png differ diff --git a/mods/creative/textures/creative_search_icon.png b/mods/creative/textures/creative_search_icon.png new file mode 100644 index 0000000..aace804 Binary files /dev/null and b/mods/creative/textures/creative_search_icon.png differ diff --git a/mods/creative/textures/creative_trash_icon.png b/mods/creative/textures/creative_trash_icon.png new file mode 100644 index 0000000..7d7a0a6 Binary files /dev/null and b/mods/creative/textures/creative_trash_icon.png differ diff --git a/mods/default/README.txt b/mods/default/README.txt new file mode 100644 index 0000000..a534697 --- /dev/null +++ b/mods/default/README.txt @@ -0,0 +1,376 @@ +Minetest Game mod: default +========================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by celeron55, Perttu Ahola (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +The torch code was derived by sofar from the 'torches' mod by +BlockMen (LGPLv2.1+) + +Authors of media (textures, sounds, models and schematics) +---------------------------------------------------------- +Everything not listed in here: +celeron55, Perttu Ahola (CC BY-SA 3.0) + + +Textures +-------- +Cisoun's texture pack (CC BY-SA 3.0): + default_jungletree.png + default_lava.png + default_leaves.png + default_sapling.png + default_bush_sapling.png + default_stone.png + default_tree.png + default_tree_top.png + default_water.png + +RealBadAngel's animated water (CC BY-SA 3.0): + default_water_source_animated.png + default_water_flowing_animated.png + +VanessaE (CC BY-SA 3.0): + default_torch_animated.png + default_torch_on_ceiling_animated.png + default_torch_on_floor_animated.png + default_torch_on_floor.png + default_desert_sand.png + default_desert_stone.png + default_sand.png + default_mese_crystal.png + default_mese_crystal_fragment.png + +Calinou (CC BY-SA 3.0): + default_brick.png + default_papyrus.png + default_mineral_copper.png + +PilzAdam (CC BY-SA 3.0): + default_jungleleaves.png + default_junglesapling.png + default_obsidian_glass.png + default_obsidian_shard.png + default_mineral_gold.png + +jojoa1997 (CC BY-SA 3.0): + default_obsidian.png + +InfinityProject (CC BY-SA 3.0): + default_mineral_diamond.png + +Splizard (CC BY-SA 3.0): + default_pine_sapling.png + default_pine_needles.png + +Zeg9 (CC BY-SA 3.0): + default_coal_block.png + +paramat (CC BY-SA 3.0): + wieldhand.png -- Copied from character.png by Jordach (CC BY-SA 3.0) + default_pinetree.png + default_pinetree_top.png + default_pinewood.png + default_acacia_leaves.png + default_acacia_leaves_simple.png + default_acacia_sapling.png + default_acacia_bush_sapling.png + default_pine_bush_sapling.png + default_acacia_tree.png + default_acacia_tree_top.png + default_acacia_wood.png + default_acacia_bush_stem.png + default_bush_stem.png + default_pine_bush_stem.png + default_junglewood.png + default_jungletree_top.png + default_sandstone_brick.png + default_obsidian_brick.png + default_stone_brick.png + default_desert_stone_brick.png + default_sandstone_block.png + default_obsidian_block.png + default_stone_block.png + default_desert_stone_block.png + default_river_water.png + default_river_water_source_animated.png + default_river_water_flowing_animated.png + default_dry_grass.png + default_dry_grass_side.png + default_dry_grass_*.png + default_grass.png + 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) + default_bookshelf_slot.png -- Derived from a texture by Gambit (CC-BY-SA 3.0) + default_marram_grass_*.png -- Derived from textures by TumeniNodes (CC-BY-SA 3.0) + default_emergent_jungle_sapling.png + default_permafrost.png -- Derived from a texture by Neuromancer (CC BY-SA 3.0) + default_stones.png -- Derived from a texture by sofar (CC0 1.0) + default_moss.png + default_moss_side.png + default_fence_rail_acacia_wood + default_fence_rail_aspen_wood -- Derived from a texture by sofar (CC BY-SA 3.0) + default_fence_rail_junglewood + default_fence_rail_pine_wood + default_fence_rail_wood -- Derived from a texture by BlockMen (CC BY-SA 3.0) + +TumeniNodes (CC BY-SA 3.0): + default_desert_cobble.png -- Derived from a texture by brunob.santos (CC BY-SA 3.0) + default_coniferous_litter.png + default_coniferous_litter_side.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 + default_gold_ingot.png + default_tool_steelsword.png + default_diamond.png + default_tool_*.png + default_lava_source_animated.png + default_lava_flowing_animated.png + default_stick.png + default_chest_front.png + default_chest_lock.png + default_chest_side.png + default_chest_top.png + default_mineral_mese.png + default_meselamp.png + bubble.png + gui_*.png + +sofar (CC BY-SA 3.0): + default_aspen_sapling + 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 (CC0 1.0): + default_gravel.png -- Derived from Gambit's PixelBOX texture pack light gravel + +Neuromancer (CC BY-SA 3.0): + default_cobble.png, based on texture by Brane praefect + default_mossycobble.png, based on texture by Brane praefect + default_furnace_*.png + +Gambit (CC BY-SA 3.0): + default_bronze_ingot.png + default_copper_ingot.png + default_copper_lump.png + default_iron_lump.png + default_gold_lump.png + default_clay_lump.png + default_coal.png + default_grass_*.png + default_paper.png + default_diamond_block.png + default_ladder_steel.png + default_sign_wall_wood.png + default_flint.png + default_snow.png + default_snow_side.png + default_snowball.png + default_key.png + default_key_skeleton.png + default_book.png + +asl97 (CC BY-SA 3.0): + default_ice.png + +KevDoy (CC BY-SA 3.0): + heart.png + +Pithydon (CC BY-SA 3.0) + default_coral_brown.png + default_coral_orange.png + default_coral_skeleton.png + +Ferk (CC0 1.0): + default_item_smoke.png + +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 + +tobyplowy (CC BY-SA 3.0): + default_kelp.png + +CloudyProton (CC BY-SA 3.0): + default_book_written.png, based on default_book.png by Gambit + +Mossmanikin (CC BY-SA 3.0): + default_fern_*.png + +random-geek (CC BY-SA 3.0): + default_blueberries.png + default_blueberry_overlay.png + default_blueberry_bush_leaves.png, derived from default_bush_leaves (by paramat) + default_blueberry_bush_sapling.png + default_dirt.png -- Derived from a texture by Neuromancer (CC BY-SA 3.0) + +Krock (CC0 1.0): + default_glass.png + default_glass_detail.png + +Topywo (CC BY-SA 3.0) + default_coral_cyan.png + default_coral_green.png + default_coral_pink.png + + +Sounds +------ +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/ + 3: http://www.freesound.org/people/lsprice/sounds/88808/ + +Mito551 (sounds) (CC BY-SA 3.0): + default_dig_choppy.ogg + default_dig_cracky.ogg + default_dig_crumbly.1.ogg + default_dig_crumbly.2.ogg + default_dig_dig_immediate.ogg + default_dig_oddly_breakable_by_hand.ogg + default_dug_node.1.ogg + default_dug_node.2.ogg + default_grass_footstep.1.ogg + default_grass_footstep.2.ogg + default_grass_footstep.3.ogg + default_gravel_footstep.1.ogg + default_gravel_footstep.2.ogg + default_gravel_footstep.3.ogg + default_gravel_footstep.4.ogg + default_grass_footstep.1.ogg + default_place_node.1.ogg + default_place_node.2.ogg + default_place_node.3.ogg + default_place_node_hard.1.ogg + default_place_node_hard.2.ogg + default_hard_footstep.1.ogg + default_hard_footstep.2.ogg + default_hard_footstep.3.ogg + default_sand_footstep.1.ogg + default_sand_footstep.2.ogg + default_wood_footstep.1.ogg + default_wood_footstep.2.ogg + default_dirt_footstep.1.ogg + default_dirt_footstep.2.ogg + default_glass_footstep.ogg + +Metal sounds: + default_dig_metal.ogg - yadronoff - CC-BY-3.0 + - https://www.freesound.org/people/yadronoff/sounds/320397/ + default_dug_metal.*.ogg - Iwan Gabovitch - qubodup - CC0 + - http://opengameart.org/users/qubodup + default_metal_footstep.*.ogg - Ottomaani138 - CC0 + - https://www.freesound.org/people/Ottomaani138/sounds/232692/ + default_place_node_metal.*.ogg - Ogrebane - CC0 + - http://opengameart.org/content/wood-and-metal-sound-effects-volume-2 + +Tool breaking sounds added by sofar: CC-BY-3.0 + default_tool_breaks.* - http://www.freesound.org/people/HerbertBoland/sounds/33206/ + +AGFX (CC BY 3.0): +https://www.freesound.org/people/AGFX/packs/1253/ + default_water_footstep.1.ogg + default_water_footstep.2.ogg + default_water_footstep.3.ogg +(default_water_footstep.4.ogg is silent) + +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 + +Ryding (CC0 1.0): +http://freesound.org/people/Ryding/sounds/94337/ + default_snow_footstep.*.ogg + +Ferk (CC0 1.0): + default_item_smoke.ogg, based on a sound by http://opengameart.org/users/bart + + +Models +------ +sofar (CC BY-SA 3.0): + chest_open.obj + torch_ceiling.obj + torch_floor.obj + torch_wall.obj + + +Schematics +---------- +paramat (CC BY-SA 3.0): + acacia_bush.mts + acacia_tree.mts + acacia_tree_from_sapling.mts + apple_tree.mts + apple_tree_from_sapling.mts + aspen_tree.mts + aspen_tree_from_sapling.mts + bush.mts + emergent_jungle_tree.mts + emergent_jungle_tree_from_sapling.mts + jungle_tree.mts + jungle_tree_from_sapling.mts + large_cactus.mts + papyrus.mts + pine_tree.mts + pine_tree_from_sapling.mts + snowy_pine_tree_from_sapling.mts + small_pine_tree.mts + small_pine_tree_from_sapling.mts + snowy_small_pine_tree_from_sapling.mts + +Shara RedCat (CC BY-SA 3.0): + acacia_log.mts + apple_log.mts + aspen_log.mts + jungle_log.mts + pine_log.mts + +sofar (CC BY-SA 3.0): + corals.mts + +TumeniNodes (CC BY-SA 3.0): + pine_bush.mts + +random-geek (CC BY-SA 3.0): + blueberry_bush.mts diff --git a/mods/default/aliases.lua b/mods/default/aliases.lua new file mode 100644 index 0000000..6db3fc8 --- /dev/null +++ b/mods/default/aliases.lua @@ -0,0 +1,77 @@ +-- mods/default/aliases.lua + +-- Aliases to support loading worlds using nodes following the old naming convention +-- These can also be helpful when using chat commands, for example /giveme +minetest.register_alias("stone", "default:stone") +minetest.register_alias("stone_with_coal", "default:stone_with_coal") +minetest.register_alias("stone_with_iron", "default:stone_with_iron") +minetest.register_alias("dirt_with_grass", "default:dirt_with_grass") +minetest.register_alias("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps") +minetest.register_alias("dirt", "default:dirt") +minetest.register_alias("sand", "default:sand") +minetest.register_alias("gravel", "default:gravel") +minetest.register_alias("sandstone", "default:sandstone") +minetest.register_alias("clay", "default:clay") +minetest.register_alias("brick", "default:brick") +minetest.register_alias("tree", "default:tree") +minetest.register_alias("jungletree", "default:jungletree") +minetest.register_alias("junglegrass", "default:junglegrass") +minetest.register_alias("leaves", "default:leaves") +minetest.register_alias("cactus", "default:cactus") +minetest.register_alias("papyrus", "default:papyrus") +minetest.register_alias("bookshelf", "default:bookshelf") +minetest.register_alias("glass", "default:glass") +minetest.register_alias("wooden_fence", "default:fence_wood") +minetest.register_alias("rail", "carts:rail") +minetest.register_alias("ladder", "default:ladder_wood") +minetest.register_alias("wood", "default:wood") +minetest.register_alias("mese", "default:mese") +minetest.register_alias("cloud", "default:cloud") +minetest.register_alias("water_flowing", "default:water_flowing") +minetest.register_alias("water_source", "default:water_source") +minetest.register_alias("lava_flowing", "default:lava_flowing") +minetest.register_alias("lava_source", "default:lava_source") +minetest.register_alias("torch", "default:torch") +minetest.register_alias("sign_wall", "default:sign_wall_wood") +minetest.register_alias("furnace", "default:furnace") +minetest.register_alias("chest", "default:chest") +minetest.register_alias("locked_chest", "default:chest_locked") +minetest.register_alias("cobble", "default:cobble") +minetest.register_alias("mossycobble", "default:mossycobble") +minetest.register_alias("steelblock", "default:steelblock") +minetest.register_alias("sapling", "default:sapling") +minetest.register_alias("apple", "default:apple") + +minetest.register_alias("WPick", "default:pick_wood") +minetest.register_alias("STPick", "default:pick_stone") +minetest.register_alias("SteelPick", "default:pick_steel") +minetest.register_alias("MesePick", "default:pick_mese") +minetest.register_alias("WShovel", "default:shovel_wood") +minetest.register_alias("STShovel", "default:shovel_stone") +minetest.register_alias("SteelShovel", "default:shovel_steel") +minetest.register_alias("WAxe", "default:axe_wood") +minetest.register_alias("STAxe", "default:axe_stone") +minetest.register_alias("SteelAxe", "default:axe_steel") +minetest.register_alias("WSword", "default:sword_wood") +minetest.register_alias("STSword", "default:sword_stone") +minetest.register_alias("SteelSword", "default:sword_steel") + +minetest.register_alias("Stick", "default:stick") +minetest.register_alias("paper", "default:paper") +minetest.register_alias("book", "default:book") +minetest.register_alias("lump_of_coal", "default:coal_lump") +minetest.register_alias("lump_of_iron", "default:iron_lump") +minetest.register_alias("lump_of_clay", "default:clay_lump") +minetest.register_alias("steel_ingot", "default:steel_ingot") +minetest.register_alias("clay_brick", "default:clay_brick") +minetest.register_alias("snow", "default:snow") + +-- 'mese_block' was used for a while for the block form of mese +minetest.register_alias("default:mese_block", "default:mese") + +-- Aliases for corrected pine node names +minetest.register_alias("default:pinetree", "default:pine_tree") +minetest.register_alias("default:pinewood", "default:pine_wood") + +minetest.register_alias("default:ladder", "default:ladder_wood") +minetest.register_alias("default:sign_wall", "default:sign_wall_wood") diff --git a/mods/default/chests.lua b/mods/default/chests.lua new file mode 100644 index 0000000..3338905 --- /dev/null +++ b/mods/default/chests.lua @@ -0,0 +1,321 @@ +default.chest = {} + +function default.chest.get_chest_formspec(pos) + local spos = pos.x .. "," .. pos.y .. "," .. pos.z + local formspec = + "size[8,9]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[nodemeta:" .. spos .. ";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[nodemeta:" .. spos .. ";main]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,4.85) + return formspec +end + +function default.chest.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 and + (def.drawtype == "airlike" or + def.drawtype == "signlike" or + def.drawtype == "torchlike" or + (def.drawtype == "nodebox" and def.paramtype2 == "wallmounted")) then + return false + end + return true +end + +function default.chest.chest_lid_close(pn) + local chest_open_info = default.chest.open_chests[pn] + local pos = chest_open_info.pos + local sound = chest_open_info.sound + local swap = chest_open_info.swap + + default.chest.open_chests[pn] = nil + for k, v in pairs(default.chest.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 + + local node = minetest.get_node(pos) + 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}) +end + +default.chest.open_chests = {} + +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 default.chest.open_chests[pn] then + return + end + + default.chest.chest_lid_close(pn) + return true +end) + +minetest.register_on_leaveplayer(function(player) + local pn = player:get_player_name() + if default.chest.open_chests[pn] then + default.chest.chest_lid_close(pn) + end +end) + +function default.chest.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 default.chest.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", default.chest.get_chest_formspec(pos)) + default.chest.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 itemstack:get_metadata() == "" then + return + end + + 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", + default.chest.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 default.chest.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", default.chest.get_chest_formspec(pos)) + default.chest.open_chests[clicker:get_player_name()] = { pos = pos, + sound = def.sound_close, swap = name } + end + def.on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "main", drops) + drops[#drops+1] = "default:" .. name + minetest.remove_node(pos) + return drops + 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 + 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 + 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 + + local def_opened = table.copy(def) + local def_closed = table.copy(def) + + def_opened.mesh = "chest_open.obj" + for i = 1, #def_opened.tiles do + if type(def_opened.tiles[i]) == "string" then + def_opened.tiles[i] = {name = def_opened.tiles[i], backface_culling = true} + elseif def_opened.tiles[i].backface_culling == nil then + def_opened.tiles[i].backface_culling = true + end + end + 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_opened.on_blast = function() 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.chest.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(), + sound_open = "default_chest_open", + sound_close = "default_chest_close", + groups = {choppy = 2, oddly_breakable_by_hand = 2}, +}) + +default.chest.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, +}) diff --git a/mods/default/crafting.lua b/mods/default/crafting.lua new file mode 100644 index 0000000..b8651c0 --- /dev/null +++ b/mods/default/crafting.lua @@ -0,0 +1,1235 @@ +-- mods/default/crafting.lua + +minetest.register_craft({ + output = 'default:wood 4', + recipe = { + {'default:tree'}, + } +}) + +minetest.register_craft({ + output = 'default:junglewood 4', + recipe = { + {'default:jungletree'}, + } +}) + +minetest.register_craft({ + output = 'default:pine_wood 4', + recipe = { + {'default:pine_tree'}, + } +}) + +minetest.register_craft({ + output = 'default:acacia_wood 4', + recipe = { + {'default:acacia_tree'}, + } +}) + +minetest.register_craft({ + output = 'default:aspen_wood 4', + recipe = { + {'default:aspen_tree'}, + } +}) + +minetest.register_craft({ + output = 'default:wood', + recipe = { + {'default:bush_stem'}, + } +}) + +minetest.register_craft({ + output = 'default:acacia_wood', + recipe = { + {'default:acacia_bush_stem'}, + } +}) + +minetest.register_craft({ + output = "default:pine_wood", + recipe = { + {"default:pine_bush_stem"}, + } +}) + +minetest.register_craft({ + output = 'default:stick 4', + recipe = { + {'group:wood'}, + } +}) + +minetest.register_craft({ + output = 'default:sign_wall_steel 3', + recipe = { + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:sign_wall_wood 3', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:torch 4', + recipe = { + {'default:coal_lump'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:pick_wood', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:pick_stone', + recipe = { + {'group:stone', 'group:stone', 'group:stone'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:pick_steel', + recipe = { + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:pick_bronze', + recipe = { + {'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:pick_mese', + recipe = { + {'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:pick_diamond', + recipe = { + {'default:diamond', 'default:diamond', 'default:diamond'}, + {'', 'group:stick', ''}, + {'', 'group:stick', ''}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_wood', + recipe = { + {'group:wood'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_stone', + recipe = { + {'group:stone'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_steel', + recipe = { + {'default:steel_ingot'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_bronze', + recipe = { + {'default:bronze_ingot'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_mese', + recipe = { + {'default:mese_crystal'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:shovel_diamond', + recipe = { + {'default:diamond'}, + {'group:stick'}, + {'group:stick'}, + } +}) + +-- Axes +-- Recipes face left to match appearence in textures and inventory + +minetest.register_craft({ + output = 'default:axe_wood', + recipe = { + {'group:wood', 'group:wood'}, + {'group:wood', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:axe_stone', + recipe = { + {'group:stone', 'group:stone'}, + {'group:stone', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:axe_steel', + recipe = { + {'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:axe_bronze', + recipe = { + {'default:bronze_ingot', 'default:bronze_ingot'}, + {'default:bronze_ingot', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:axe_mese', + recipe = { + {'default:mese_crystal', 'default:mese_crystal'}, + {'default:mese_crystal', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:axe_diamond', + recipe = { + {'default:diamond', 'default:diamond'}, + {'default:diamond', 'group:stick'}, + {'', 'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_wood', + recipe = { + {'group:wood'}, + {'group:wood'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_stone', + recipe = { + {'group:stone'}, + {'group:stone'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_steel', + recipe = { + {'default:steel_ingot'}, + {'default:steel_ingot'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_bronze', + recipe = { + {'default:bronze_ingot'}, + {'default:bronze_ingot'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_mese', + recipe = { + {'default:mese_crystal'}, + {'default:mese_crystal'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:sword_diamond', + recipe = { + {'default:diamond'}, + {'default:diamond'}, + {'group:stick'}, + } +}) + +minetest.register_craft({ + output = 'default:skeleton_key', + recipe = { + {'default:gold_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:chest', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', '', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + } +}) + +minetest.register_craft({ + output = 'default:chest_locked', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', 'default:steel_ingot', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + } +}) + +minetest.register_craft( { + type = "shapeless", + output = "default:chest_locked", + recipe = {"default:chest", "default:steel_ingot"}, +}) + +minetest.register_craft({ + output = 'default:furnace', + recipe = { + {'group:stone', 'group:stone', 'group:stone'}, + {'group:stone', '', 'group:stone'}, + {'group:stone', 'group:stone', 'group:stone'}, + } +}) + +minetest.register_craft({ + output = 'default:coalblock', + recipe = { + {'default:coal_lump', 'default:coal_lump', 'default:coal_lump'}, + {'default:coal_lump', 'default:coal_lump', 'default:coal_lump'}, + {'default:coal_lump', 'default:coal_lump', 'default:coal_lump'}, + } +}) + +minetest.register_craft({ + output = 'default:coal_lump 9', + recipe = { + {'default:coalblock'}, + } +}) + +minetest.register_craft({ + output = 'default:steelblock', + recipe = { + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:steel_ingot 9', + recipe = { + {'default:steelblock'}, + } +}) + +minetest.register_craft({ + output = 'default:copperblock', + recipe = { + {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}, + {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}, + {'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:copper_ingot 9', + recipe = { + {'default:copperblock'}, + } +}) + +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 = { + {'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'}, + {'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'}, + {'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:bronze_ingot 9', + recipe = { + {'default:bronzeblock'}, + } +}) + +minetest.register_craft({ + output = 'default:goldblock', + recipe = { + {'default:gold_ingot', 'default:gold_ingot', 'default:gold_ingot'}, + {'default:gold_ingot', 'default:gold_ingot', 'default:gold_ingot'}, + {'default:gold_ingot', 'default:gold_ingot', 'default:gold_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:gold_ingot 9', + recipe = { + {'default:goldblock'}, + } +}) + +minetest.register_craft({ + output = 'default:diamondblock', + recipe = { + {'default:diamond', 'default:diamond', 'default:diamond'}, + {'default:diamond', 'default:diamond', 'default:diamond'}, + {'default:diamond', 'default:diamond', 'default:diamond'}, + } +}) + +minetest.register_craft({ + output = 'default:diamond 9', + recipe = { + {'default:diamondblock'}, + } +}) + +minetest.register_craft({ + output = "default:sandstone", + recipe = { + {"default:sand", "default:sand"}, + {"default:sand", "default:sand"}, + } +}) + +minetest.register_craft({ + output = "default:sand 4", + recipe = { + {"default:sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:sandstonebrick 4", + recipe = { + {"default:sandstone", "default:sandstone"}, + {"default:sandstone", "default:sandstone"}, + } +}) + +minetest.register_craft({ + output = "default:sandstone_block 9", + recipe = { + {"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"}, + } +}) + +minetest.register_craft({ + output = 'default:clay', + recipe = { + {'default:clay_lump', 'default:clay_lump'}, + {'default:clay_lump', 'default:clay_lump'}, + } +}) + +minetest.register_craft({ + output = 'default:clay_lump 4', + recipe = { + {'default:clay'}, + } +}) + +minetest.register_craft({ + output = 'default:brick', + recipe = { + {'default:clay_brick', 'default:clay_brick'}, + {'default:clay_brick', 'default:clay_brick'}, + } +}) + +minetest.register_craft({ + output = 'default:clay_brick 4', + recipe = { + {'default:brick'}, + } +}) + +minetest.register_craft({ + output = 'default:paper', + recipe = { + {'default:papyrus', 'default:papyrus', 'default:papyrus'}, + } +}) + +minetest.register_craft({ + output = 'default:book', + recipe = { + {'default:paper'}, + {'default:paper'}, + {'default:paper'}, + } +}) + +minetest.register_craft({ + output = 'default:bookshelf', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'default:book', 'default:book', 'default:book'}, + {'group:wood', 'group:wood', 'group:wood'}, + } +}) + +minetest.register_craft({ + output = "default:ladder_wood 5", + recipe = { + {"group:stick", "", "group:stick"}, + {"group:stick", "group:stick", "group:stick"}, + {"group:stick", "", "group:stick"}, + } +}) + +minetest.register_craft({ + output = 'default:ladder_steel 15', + recipe = { + {'default:steel_ingot', '', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', '', 'default:steel_ingot'}, + } +}) + +minetest.register_craft({ + output = 'default:mese', + recipe = { + {'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'}, + {'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'}, + {'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'}, + } +}) + +minetest.register_craft({ + output = 'default:mese_crystal 9', + recipe = { + {'default:mese'}, + } +}) + +minetest.register_craft({ + output = 'default:mese_crystal_fragment 9', + recipe = { + {'default:mese_crystal'}, + } +}) + +minetest.register_craft({ + output = "default:mese_crystal", + recipe = { + {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"}, + {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"}, + {"default:mese_crystal_fragment", "default:mese_crystal_fragment", "default:mese_crystal_fragment"}, + } +}) + +minetest.register_craft({ + output = 'default:meselamp', + recipe = { + {'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", ""}, + } +}) + +minetest.register_craft({ + output = 'default:obsidian_shard 9', + recipe = { + {'default:obsidian'} + } +}) + +minetest.register_craft({ + output = 'default:obsidian', + recipe = { + {'default:obsidian_shard', 'default:obsidian_shard', 'default:obsidian_shard'}, + {'default:obsidian_shard', 'default:obsidian_shard', 'default:obsidian_shard'}, + {'default:obsidian_shard', 'default:obsidian_shard', 'default:obsidian_shard'}, + } +}) + +minetest.register_craft({ + output = 'default:obsidianbrick 4', + recipe = { + {'default:obsidian', 'default:obsidian'}, + {'default:obsidian', 'default:obsidian'} + } +}) + +minetest.register_craft({ + output = 'default:obsidian_block 9', + recipe = { + {'default:obsidian', 'default:obsidian', 'default:obsidian'}, + {'default:obsidian', 'default:obsidian', 'default:obsidian'}, + {'default:obsidian', 'default:obsidian', 'default:obsidian'}, + } +}) + +minetest.register_craft({ + output = 'default:stonebrick 4', + recipe = { + {'default:stone', 'default:stone'}, + {'default:stone', 'default:stone'}, + } +}) + +minetest.register_craft({ + output = 'default:stone_block 9', + recipe = { + {'default:stone', 'default:stone', 'default:stone'}, + {'default:stone', 'default:stone', 'default:stone'}, + {'default:stone', 'default:stone', 'default:stone'}, + } +}) + +minetest.register_craft({ + output = 'default:desert_stonebrick 4', + recipe = { + {'default:desert_stone', 'default:desert_stone'}, + {'default:desert_stone', 'default:desert_stone'}, + } +}) + +minetest.register_craft({ + output = 'default:desert_stone_block 9', + recipe = { + {'default:desert_stone', 'default:desert_stone', 'default:desert_stone'}, + {'default:desert_stone', 'default:desert_stone', 'default:desert_stone'}, + {'default:desert_stone', 'default:desert_stone', 'default:desert_stone'}, + } +}) + +minetest.register_craft({ + output = 'default:snowblock', + recipe = { + {'default:snow', 'default:snow', 'default:snow'}, + {'default:snow', 'default:snow', 'default:snow'}, + {'default:snow', 'default:snow', 'default:snow'}, + } +}) + +minetest.register_craft({ + output = 'default:snow 9', + recipe = { + {'default:snowblock'}, + } +}) + +minetest.register_craft({ + output = "default:emergent_jungle_sapling", + recipe = { + {"default:junglesapling", "default:junglesapling", "default:junglesapling"}, + {"default:junglesapling", "default:junglesapling", "default:junglesapling"}, + {"default:junglesapling", "default:junglesapling", "default:junglesapling"}, + } +}) + + +-- +-- Crafting (tool repair) +-- + +minetest.register_craft({ + type = "toolrepair", + additional_wear = -0.02, +}) + + +-- +-- Cooking recipes +-- + +minetest.register_craft({ + type = "cooking", + output = "default:glass", + recipe = "group:sand", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:obsidian_glass", + recipe = "default:obsidian_shard", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:stone", + recipe = "default:cobble", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:stone", + recipe = "default:mossycobble", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:desert_stone", + recipe = "default:desert_cobble", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:steel_ingot", + recipe = "default:iron_lump", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:copper_ingot", + 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", + recipe = "default:gold_lump", +}) + +minetest.register_craft({ + type = "cooking", + output = "default:clay_brick", + recipe = "default:clay_lump", +}) + +minetest.register_craft({ + type = 'cooking', + output = 'default:gold_ingot', + recipe = 'default:skeleton_key', + cooktime = 5, +}) + +minetest.register_craft({ + type = 'cooking', + output = 'default:gold_ingot', + recipe = 'default:key', + cooktime = 5, +}) + + +-- +-- Fuels +-- + +-- Support use of group:tree, includes default:tree which has the same burn time +minetest.register_craft({ + type = "fuel", + recipe = "group:tree", + burntime = 30, +}) + +-- Burn time for all woods are in order of wood density, +-- which is also the order of wood colour darkness: +-- aspen, pine, apple, acacia, jungle + +minetest.register_craft({ + type = "fuel", + recipe = "default:aspen_tree", + burntime = 22, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:pine_tree", + burntime = 26, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_tree", + burntime = 34, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:jungletree", + burntime = 38, +}) + + +-- Support use of group:wood, includes default:wood which has the same burn time +minetest.register_craft({ + type = "fuel", + recipe = "group:wood", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:aspen_wood", + burntime = 5, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:pine_wood", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_wood", + burntime = 8, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:junglewood", + burntime = 9, +}) + + +-- Support use of group:sapling, includes default:sapling which has the same burn time +minetest.register_craft({ + type = "fuel", + recipe = "group:sapling", + burntime = 5, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:bush_sapling", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_bush_sapling", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:pine_bush_sapling", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:aspen_sapling", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:pine_sapling", + burntime = 5, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_sapling", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:junglesapling", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:emergent_jungle_sapling", + burntime = 7, +}) + + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_aspen_wood", + burntime = 5, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_pine_wood", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_wood", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_acacia_wood", + burntime = 8, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_junglewood", + burntime = 9, +}) + + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_rail_aspen_wood", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_rail_pine_wood", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_rail_wood", + burntime = 5, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_rail_acacia_wood", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fence_rail_junglewood", + burntime = 7, +}) + + +minetest.register_craft({ + type = "fuel", + recipe = "default:bush_stem", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:acacia_bush_stem", + burntime = 8, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:pine_bush_stem", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:junglegrass", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "group:leaves", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:cactus", + burntime = 15, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:papyrus", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:bookshelf", + burntime = 30, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:ladder_wood", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:lava_source", + burntime = 60, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:torch", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:sign_wall_wood", + burntime = 10, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:chest", + burntime = 30, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:chest_locked", + burntime = 30, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:coal_lump", + burntime = 40, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:coalblock", + burntime = 370, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:grass_1", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:dry_grass_1", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:fern_1", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:marram_grass_1", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:paper", + burntime = 1, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:book", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:book_written", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:dry_shrub", + burntime = 2, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "group:stick", + burntime = 1, +}) + + +minetest.register_craft({ + type = "fuel", + recipe = "default:pick_wood", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:shovel_wood", + burntime = 4, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:axe_wood", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "default:sword_wood", + burntime = 5, +}) diff --git a/mods/default/craftitems.lua b/mods/default/craftitems.lua new file mode 100644 index 0000000..3e3852c --- /dev/null +++ b/mods/default/craftitems.lua @@ -0,0 +1,349 @@ +-- mods/default/craftitems.lua + +minetest.register_craftitem("default:stick", { + description = "Stick", + inventory_image = "default_stick.png", + groups = {stick = 1, flammable = 2}, +}) + +minetest.register_craftitem("default:paper", { + description = "Paper", + inventory_image = "default_paper.png", + 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 meta = itemstack:get_meta() + local title, text, owner = "", "", player_name + local page, page_max, lines, string = 1, 1, {}, "" + + -- 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 + + for str in (text .. "\n"):gmatch("([^\n]*)[\n]") do + lines[#lines+1] = str + end + + if data.page then + page = data.page + page_max = data.page_max + + for i = ((lpp * page) - lpp) + 1, lpp * page do + if not lines[i] then break end + string = string .. lines[i] .. "\n" + end + end + end + + local formspec + if owner == player_name then + formspec = "size[8,8]" .. default.gui_bg .. + default.gui_bg_img .. + "field[0.5,1;7.5,0;title;Title:;" .. + minetest.formspec_escape(title) .. "]" .. + "textarea[0.5,1.5;7.5,7;text;Contents:;" .. + minetest.formspec_escape(text) .. "]" .. + "button_exit[2.5,7.5;3,1;save;Save]" + else + formspec = "size[8,8]" .. default.gui_bg .. + default.gui_bg_img .. + "label[0.5,0.5;by " .. owner .. "]" .. + "tablecolumns[color;text]" .. + "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. + "table[0.4,0;7,0.5;title;#FFFF00," .. minetest.formspec_escape(title) .. "]" .. + "textarea[0.5,1.5;7.5,7;;" .. + minetest.formspec_escape(string ~= "" and string or text) .. ";]" .. + "button[2.4,7.6;0.8,0.8;book_prev;<]" .. + "label[3.2,7.7;Page " .. page .. " of " .. page_max .. "]" .. + "button[4.9,7.6;0.8,0.8;book_next;>]" + end + + minetest.show_formspec(player_name, "default:book", formspec) + return itemstack +end + +local max_text_size = 10000 +local max_title_size = 80 +local short_title_size = 35 +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "default:book" then return end + local inv = player:get_inventory() + local stack = player:get_wielded_item() + + if fields.save and fields.title and fields.text + and fields.title ~= "" and fields.text ~= "" then + local new_stack, data + if stack:get_name() ~= "default:book_written" then + local count = stack:get_count() + if count == 1 then + stack:set_name("default:book_written") + else + stack:set_count(count - 1) + new_stack = ItemStack("default:book_written") + end + else + 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:sub(1, max_title_size) + data.owner = player:get_player_name() + local short_title = data.title + -- Don't bother triming the title if the trailing dots would make it longer + if #short_title > short_title_size + 3 then + short_title = short_title:sub(1, short_title_size) .. "..." + end + data.description = "\""..short_title.."\" by "..data.owner + data.text = fields.text:sub(1, max_text_size) + data.text = data.text:gsub("\r\n", "\n"):gsub("\r", "\n") + data.page = 1 + data.page_max = math.ceil((#data.text:gsub("[^\n]", "") + 1) / lpp) + + if new_stack then + 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:get_pos(), new_stack) + end + else + stack:get_meta():from_table({ fields = data }) + end + + elseif fields.book_next or fields.book_prev then + 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 + data.page = 1 + end + else + data.page = data.page - 1 + if data.page == 0 then + data.page = data.page_max + end + end + + stack:get_meta():from_table({fields = data}) + stack = book_on_use(stack, player) + end + + -- Update stack + player:set_wielded_item(stack) +end) + +minetest.register_craftitem("default:book", { + description = "Book", + inventory_image = "default_book.png", + groups = {book = 1, flammable = 3}, + on_use = book_on_use, +}) + +minetest.register_craftitem("default:book_written", { + description = "Book With Text", + inventory_image = "default_book_written.png", + groups = {book = 1, not_in_creative_inventory = 1, flammable = 3}, + stack_max = 1, + on_use = book_on_use, +}) + +minetest.register_craft({ + type = "shapeless", + output = "default:book_written", + recipe = {"default:book", "default:book_written"} +}) + +minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + if itemstack:get_name() ~= "default:book_written" then + return + end + + local original + local index + for i = 1, player:get_inventory():get_size("craft") do + if old_craft_grid[i]:get_name() == "default:book_written" then + original = old_craft_grid[i] + index = i + end + end + if not original then + return + end + local copymeta = original:get_meta():to_table() + -- copy of the book held by player's mouse cursor + 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:get_pos(), 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", + groups = {coal = 1, flammable = 1} +}) + +minetest.register_craftitem("default:iron_lump", { + description = "Iron Lump", + inventory_image = "default_iron_lump.png", +}) + +minetest.register_craftitem("default:copper_lump", { + description = "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", +}) + +minetest.register_craftitem("default:gold_lump", { + description = "Gold Lump", + inventory_image = "default_gold_lump.png", +}) + +minetest.register_craftitem("default:diamond", { + description = "Diamond", + inventory_image = "default_diamond.png", +}) + +minetest.register_craftitem("default:clay_lump", { + description = "Clay Lump", + inventory_image = "default_clay_lump.png", +}) + +minetest.register_craftitem("default:steel_ingot", { + description = "Steel Ingot", + inventory_image = "default_steel_ingot.png", +}) + +minetest.register_craftitem("default:copper_ingot", { + description = "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", +}) + +minetest.register_craftitem("default:gold_ingot", { + description = "Gold Ingot", + inventory_image = "default_gold_ingot.png" +}) + +minetest.register_craftitem("default:mese_crystal_fragment", { + description = "Mese Crystal Fragment", + inventory_image = "default_mese_crystal_fragment.png", +}) + +minetest.register_craftitem("default:clay_brick", { + description = "Clay Brick", + inventory_image = "default_clay_brick.png", +}) + +minetest.register_craftitem("default:obsidian_shard", { + description = "Obsidian Shard", + inventory_image = "default_obsidian_shard.png", +}) + +minetest.register_craftitem("default:flint", { + description = "Flint", + inventory_image = "default_flint.png" +}) + +minetest.register_craftitem("default:blueberries", { + description = "Blueberries", + inventory_image = "default_blueberries.png", + on_use = minetest.item_eat(2), +}) diff --git a/mods/default/depends.txt b/mods/default/depends.txt new file mode 100644 index 0000000..19ce2fc --- /dev/null +++ b/mods/default/depends.txt @@ -0,0 +1,2 @@ +dye +player_api? diff --git a/mods/default/functions.lua b/mods/default/functions.lua new file mode 100644 index 0000000..55ea3f2 --- /dev/null +++ b/mods/default/functions.lua @@ -0,0 +1,605 @@ +-- +-- Sounds +-- + +function default.node_sound_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "", gain = 0.1} + table.dug = table.dug or + {name = "default_dug_node", gain = 0.25} + table.place = table.place or + {name = "default_place_node_hard", gain = 1.0} + return table +end + +function default.node_sound_stone_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_hard_footstep", gain = 0.13} + table.dug = table.dug or + {name = "default_hard_footstep", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_dirt_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_dirt_footstep", gain = 0.14} + table.dug = table.dug or + {name = "default_dirt_footstep", gain = 1.0} + table.place = table.place or + {name = "default_place_node", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_sand_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_sand_footstep", gain = 0.012} + table.dug = table.dug or + {name = "default_sand_footstep", gain = 0.24} + table.place = table.place or + {name = "default_place_node", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_gravel_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_gravel_footstep", gain = 0.14} + table.dug = table.dug or + {name = "default_gravel_footstep", gain = 1.0} + table.place = table.place or + {name = "default_place_node", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_wood_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_wood_footstep", gain = 0.13} + table.dug = table.dug or + {name = "default_wood_footstep", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_leaves_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_grass_footstep", gain = 0.145} + table.dug = table.dug or + {name = "default_grass_footstep", gain = 0.7} + table.place = table.place or + {name = "default_place_node", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_glass_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_glass_footstep", gain = 0.13} + table.dig = table.dig or + {name = "default_glass_footstep", gain = 0.5} + table.dug = table.dug or + {name = "default_break_glass", gain = 1.0} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_metal_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_metal_footstep", gain = 0.14} + table.dig = table.dig or + {name = "default_dig_metal", gain = 0.5} + table.dug = table.dug or + {name = "default_dug_metal", gain = 0.5} + table.place = table.place or + {name = "default_place_node_metal", gain = 0.5} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_water_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_water_footstep", gain = 0.12} + default.node_sound_defaults(table) + return table +end + +function default.node_sound_snow_defaults(table) + table = table or {} + table.footstep = table.footstep or + {name = "default_snow_footstep", gain = 0.12} + table.dig = table.dig or + {name = "default_snow_footstep", gain = 0.3} + table.dug = table.dug or + {name = "default_snow_footstep", gain = 0.3} + table.place = table.place or + {name = "default_place_node", gain = 1.0} + default.node_sound_defaults(table) + return table +end + + +-- +-- Lavacooling +-- + +default.cool_lava = function(pos, node) + if node.name == "default:lava_source" then + minetest.set_node(pos, {name = "default:obsidian"}) + else -- Lava flowing + minetest.set_node(pos, {name = "default:stone"}) + end + minetest.sound_play("default_cool_lava", + {pos = pos, max_hear_distance = 16, gain = 0.25}) +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 = 2, + chance = 2, + catch_up = false, + action = function(...) + default.cool_lava(...) + end, + }) +end + + +-- +-- Optimized helper to put all items in an inventory into a drops list +-- + +function default.get_inventory_drops(pos, inventory, drops) + local inv = minetest.get_meta(pos):get_inventory() + local n = #drops + for i = 1, inv:get_size(inventory) do + local stack = inv:get_stack(inventory, i) + if stack:get_count() > 0 then + drops[n+1] = stack:to_table() + n = n + 1 + end + end +end + + +-- +-- Papyrus and cactus growing +-- + +-- Wrapping the functions in ABM action is necessary to make overriding them possible + +function default.grow_cactus(pos, node) + if node.param2 >= 4 then + return + end + pos.y = pos.y - 1 + if minetest.get_item_group(minetest.get_node(pos).name, "sand") == 0 then + return + end + pos.y = pos.y + 1 + local height = 0 + while node.name == "default:cactus" and height < 4 do + height = height + 1 + pos.y = pos.y + 1 + node = minetest.get_node(pos) + end + 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 + +function default.grow_papyrus(pos, node) + pos.y = pos.y - 1 + local name = minetest.get_node(pos).name + if name ~= "default:dirt_with_grass" and name ~= "default:dirt" then + return + end + if not minetest.find_node_near(pos, 3, {"group:water"}) then + return + end + pos.y = pos.y + 1 + local height = 0 + while node.name == "default:papyrus" and height < 4 do + height = height + 1 + pos.y = pos.y + 1 + node = minetest.get_node(pos) + end + 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 + +minetest.register_abm({ + label = "Grow cactus", + nodenames = {"default:cactus"}, + neighbors = {"group:sand"}, + interval = 12, + chance = 83, + action = function(...) + default.grow_cactus(...) + end +}) + +minetest.register_abm({ + label = "Grow papyrus", + nodenames = {"default:papyrus"}, + neighbors = {"default:dirt", "default:dirt_with_grass"}, + interval = 14, + chance = 71, + action = function(...) + default.grow_papyrus(...) + end +}) + + +-- +-- Dig upwards +-- + +function default.dig_up(pos, node, digger) + if digger == nil then return end + local np = {x = pos.x, y = pos.y + 1, z = pos.z} + local nn = minetest.get_node(np) + if nn.name == node.name then + minetest.node_dig(np, nn, digger) + end +end + + +-- +-- Fence registration helper +-- + +function default.register_fence(name, def) + minetest.register_craft({ + output = name .. " 4", + recipe = { + { def.material, 'group:stick', def.material }, + { def.material, 'group:stick', def.material }, + } + }) + + local fence_texture = "default_fence_overlay.png^" .. def.texture .. + "^default_fence_overlay.png^[makealpha:255,126,126" + -- Allow almost everything to be overridden + local default_fields = { + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = {{-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}}, + -- connect_top = + -- connect_bottom = + connect_front = {{-1/16,3/16,-1/2,1/16,5/16,-1/8}, + {-1/16,-5/16,-1/2,1/16,-3/16,-1/8}}, + connect_left = {{-1/2,3/16,-1/16,-1/8,5/16,1/16}, + {-1/2,-5/16,-1/16,-1/8,-3/16,1/16}}, + connect_back = {{-1/16,3/16,1/8,1/16,5/16,1/2}, + {-1/16,-5/16,1/8,1/16,-3/16,1/2}}, + connect_right = {{1/8,3/16,-1/16,1/2,5/16,1/16}, + {1/8,-5/16,-1/16,1/2,-3/16,1/16}}, + }, + connects_to = {"group:fence", "group:wood", "group:tree", "group:wall"}, + inventory_image = fence_texture, + wield_image = fence_texture, + tiles = {def.texture}, + sunlight_propagates = true, + is_ground_content = false, + groups = {}, + } + for k, v in pairs(default_fields) do + if def[k] == nil then + def[k] = v + end + end + + -- Always add to the fence group, even if no group provided + def.groups.fence = 1 + + def.texture = nil + def.material = nil + + minetest.register_node(name, def) +end + + +-- +-- Fence rail registration helper +-- + +function default.register_fence_rail(name, def) + minetest.register_craft({ + output = name .. " 16", + recipe = { + { def.material, def.material }, + { "", ""}, + { def.material, def.material }, + } + }) + + local fence_rail_texture = "default_fence_rail_overlay.png^" .. def.texture .. + "^default_fence_rail_overlay.png^[makealpha:255,126,126" + -- Allow almost everything to be overridden + local default_fields = { + paramtype = "light", + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = { + {-1/16, 3/16, -1/16, 1/16, 5/16, 1/16}, + {-1/16, -3/16, -1/16, 1/16, -5/16, 1/16} + }, + -- connect_top = + -- connect_bottom = + connect_front = { + {-1/16, 3/16, -1/2, 1/16, 5/16, -1/16}, + {-1/16, -5/16, -1/2, 1/16, -3/16, -1/16}}, + connect_left = { + {-1/2, 3/16, -1/16, -1/16, 5/16, 1/16}, + {-1/2, -5/16, -1/16, -1/16, -3/16, 1/16}}, + connect_back = { + {-1/16, 3/16, 1/16, 1/16, 5/16, 1/2}, + {-1/16, -5/16, 1/16, 1/16, -3/16, 1/2}}, + connect_right = { + {1/16, 3/16, -1/16, 1/2, 5/16, 1/16}, + {1/16, -5/16, -1/16, 1/2, -3/16, 1/16}}, + }, + connects_to = {"group:fence", "group:wall"}, + inventory_image = fence_rail_texture, + wield_image = fence_rail_texture, + tiles = {def.texture}, + sunlight_propagates = true, + is_ground_content = false, + groups = {}, + } + for k, v in pairs(default_fields) do + if def[k] == nil then + def[k] = v + end + end + + -- Always add to the fence group, even if no group provided + def.groups.fence = 1 + + def.texture = nil + def.material = nil + + minetest.register_node(name, def) +end + + +-- +-- Leafdecay +-- + +-- Prevent decay of placed leaves + +default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) + if placer and placer:is_player() and not placer:get_player_control().sneak then + local node = minetest.get_node(pos) + node.param2 = 1 + minetest.set_node(pos, node) + end +end + +-- 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 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 + 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 +-- + +minetest.register_abm({ + label = "Grass spread", + nodenames = {"default:dirt"}, + neighbors = { + "air", + "group:grass", + "group:dry_grass", + "default:snow", + }, + interval = 6, + chance = 50, + catch_up = false, + action = function(pos, node) + -- Check for darkness: night, shadow or under a light-blocking node + -- Returns if ignore above + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + if (minetest.get_node_light(above) or 0) < 13 then + return + end + + -- Look for spreading dirt-type neighbours + local p2 = minetest.find_node_near(pos, 1, "group:spreading_dirt_type") + if p2 then + local n3 = minetest.get_node(p2) + minetest.set_node(pos, {name = n3.name}) + return + end + + -- Else, any seeding nodes on top? + local name = minetest.get_node(above).name + -- Snow check is cheapest, so comes first + if name == "default:snow" then + minetest.set_node(pos, {name = "default:dirt_with_snow"}) + -- Most likely case first + elseif minetest.get_item_group(name, "grass") ~= 0 then + minetest.set_node(pos, {name = "default:dirt_with_grass"}) + elseif minetest.get_item_group(name, "dry_grass") ~= 0 then + minetest.set_node(pos, {name = "default:dirt_with_dry_grass"}) + end + end +}) + + +-- +-- Grass and dry grass removed in darkness +-- + +minetest.register_abm({ + label = "Grass covered", + nodenames = {"group:spreading_dirt_type"}, + interval = 8, + chance = 50, + catch_up = false, + action = function(pos, node) + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + local name = minetest.get_node(above).name + local nodedef = minetest.registered_nodes[name] + if name ~= "ignore" and nodedef and not ((nodedef.sunlight_propagates or + nodedef.paramtype == "light") and + nodedef.liquidtype == "none") then + minetest.set_node(pos, {name = "default:dirt"}) + end + end +}) + + +-- +-- Moss growth on cobble near water +-- + +minetest.register_abm({ + label = "Moss growth", + nodenames = {"default:cobble", "stairs:slab_cobble", "stairs:stair_cobble", "walls:cobble"}, + neighbors = {"group:water"}, + interval = 16, + chance = 200, + catch_up = false, + action = function(pos, node) + if node.name == "default:cobble" then + minetest.set_node(pos, {name = "default:mossycobble"}) + elseif node.name == "stairs:slab_cobble" then + minetest.set_node(pos, {name = "stairs:slab_mossycobble", param2 = node.param2}) + elseif node.name == "stairs:stair_cobble" then + minetest.set_node(pos, {name = "stairs:stair_mossycobble", param2 = node.param2}) + elseif node.name == "walls:cobble" then + minetest.set_node(pos, {name = "walls:mossycobble", param2 = node.param2}) + end + 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/furnace.lua b/mods/default/furnace.lua new file mode 100644 index 0000000..09966a6 --- /dev/null +++ b/mods/default/furnace.lua @@ -0,0 +1,337 @@ + +-- +-- Formspecs +-- + +function default.get_furnace_active_formspec(fuel_percent, item_percent) + return "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:".. + (100-fuel_percent)..":default_furnace_fire_fg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:".. + (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4.25) +end + +function default.get_furnace_inactive_formspec() + return "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[context;src;2.75,0.5;1,1;]".. + "list[context;fuel;2.75,2.5;1,1;]".. + "image[2.75,1.5;1,1;default_furnace_fire_bg.png]".. + "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "list[context;dst;4.75,0.96;2,2;]".. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "listring[context;dst]".. + "listring[current_player;main]".. + "listring[context;src]".. + "listring[current_player;main]".. + "listring[context;fuel]".. + "listring[current_player;main]".. + default.get_hotbar_bg(0, 4.25) +end + +-- +-- Node callback functions that are the same for active and inactive furnace +-- + +local function can_dig(pos, player) + local meta = minetest.get_meta(pos); + local inv = meta:get_inventory() + return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src") +end + +local function allow_metadata_inventory_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if listname == "fuel" then + if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then + if inv:is_empty("src") then + meta:set_string("infotext", "Furnace is empty") + end + return stack:get_count() + else + return 0 + end + elseif listname == "src" then + return stack:get_count() + elseif listname == "dst" then + return 0 + end +end + +local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(from_list, from_index) + return allow_metadata_inventory_put(pos, to_list, to_index, stack, player) +end + +local function allow_metadata_inventory_take(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + return stack:get_count() +end + +local function swap_node(pos, name) + local node = minetest.get_node(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function furnace_node_timer(pos, elapsed) + -- + -- Inizialize metadata + -- + local meta = minetest.get_meta(pos) + local fuel_time = meta:get_float("fuel_time") or 0 + local src_time = meta:get_float("src_time") or 0 + local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 + + local inv = meta:get_inventory() + local srclist, fuellist + + local cookable, cooked + local fuel + + local update = true + while elapsed > 0 and update do + update = false + + srclist = inv:get_list("src") + fuellist = inv:get_list("fuel") + + -- + -- Cooking + -- + + -- Check if we have cookable content + local aftercooked + cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist}) + cookable = cooked.time ~= 0 + + local el = math.min(elapsed, fuel_totaltime - fuel_time) + if cookable then -- fuel lasts long enough, adjust el to cooking duration + el = math.min(el, cooked.time - src_time) + end + + -- Check if we have enough fuel to burn + if fuel_time < fuel_totaltime then + -- The furnace is currently active and has enough fuel + fuel_time = fuel_time + el + -- If there is a cookable item then check if it is ready yet + if cookable then + src_time = src_time + el + if src_time >= cooked.time then + -- Place result in dst list if possible + if inv:room_for_item("dst", cooked.item) then + inv:add_item("dst", cooked.item) + inv:set_stack("src", 1, aftercooked.items[1]) + src_time = src_time - cooked.time + update = true + end + else + -- Item could not be cooked: probably missing fuel + update = true + end + end + else + -- Furnace ran out of fuel + if cookable then + -- We need to get new fuel + local afterfuel + fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist}) + + if fuel.time == 0 then + -- No valid fuel in fuel list + fuel_totaltime = 0 + src_time = 0 + else + -- Take fuel from fuel list + inv:set_stack("fuel", 1, afterfuel.items[1]) + update = true + fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time) + end + else + -- We don't need to get new fuel since there is no cookable item + fuel_totaltime = 0 + src_time = 0 + end + fuel_time = 0 + end + + elapsed = elapsed - el + end + + if fuel and fuel_totaltime > fuel.time then + fuel_totaltime = fuel.time + end + if srclist[1]:is_empty() then + src_time = 0 + end + + -- + -- Update formspec, infotext and node + -- + local formspec + local item_state + local item_percent = 0 + if cookable then + item_percent = math.floor(src_time / cooked.time * 100) + if item_percent > 100 then + item_state = "100% (output full)" + else + item_state = item_percent .. "%" + end + else + if srclist[1]:is_empty() then + item_state = "Empty" + else + item_state = "Not cookable" + end + end + + local fuel_state = "Empty" + local active = "inactive" + local result = false + + if fuel_totaltime ~= 0 then + active = "active" + local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100) + fuel_state = fuel_percent .. "%" + formspec = default.get_furnace_active_formspec(fuel_percent, item_percent) + swap_node(pos, "default:furnace_active") + -- make sure timer restarts automatically + result = true + else + if not fuellist[1]:is_empty() then + fuel_state = "0%" + end + formspec = default.get_furnace_inactive_formspec() + swap_node(pos, "default:furnace") + -- stop timer on the inactive furnace + minetest.get_node_timer(pos):stop() + end + + local infotext = "Furnace " .. active .. "\n(Item: " .. item_state .. + "; Fuel: " .. fuel_state .. ")" + + -- + -- Set meta values + -- + meta:set_float("fuel_totaltime", fuel_totaltime) + meta:set_float("fuel_time", fuel_time) + meta:set_float("src_time", src_time) + meta:set_string("formspec", formspec) + meta:set_string("infotext", infotext) + + return result +end + +-- +-- Node definitions +-- + +minetest.register_node("default:furnace", { + description = "Furnace", + tiles = { + "default_furnace_top.png", "default_furnace_bottom.png", + "default_furnace_side.png", "default_furnace_side.png", + "default_furnace_side.png", "default_furnace_front.png" + }, + paramtype2 = "facedir", + groups = {cracky=2}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), + + can_dig = can_dig, + + on_timer = furnace_node_timer, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", default.get_furnace_inactive_formspec()) + local inv = meta:get_inventory() + inv:set_size('src', 1) + inv:set_size('fuel', 1) + inv:set_size('dst', 4) + end, + + on_metadata_inventory_move = function(pos) + minetest.get_node_timer(pos):start(1.0) + end, + on_metadata_inventory_put = function(pos) + -- start timer function, it will sort out whether furnace can burn or not. + minetest.get_node_timer(pos):start(1.0) + end, + on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "src", drops) + default.get_inventory_drops(pos, "fuel", drops) + default.get_inventory_drops(pos, "dst", drops) + drops[#drops+1] = "default:furnace" + minetest.remove_node(pos) + return drops + end, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) + +minetest.register_node("default:furnace_active", { + description = "Furnace", + tiles = { + "default_furnace_top.png", "default_furnace_bottom.png", + "default_furnace_side.png", "default_furnace_side.png", + "default_furnace_side.png", + { + image = "default_furnace_front_active.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.5 + }, + } + }, + paramtype2 = "facedir", + light_source = 8, + drop = "default:furnace", + groups = {cracky=2, not_in_creative_inventory=1}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), + on_timer = furnace_node_timer, + + can_dig = can_dig, + + allow_metadata_inventory_put = allow_metadata_inventory_put, + allow_metadata_inventory_move = allow_metadata_inventory_move, + allow_metadata_inventory_take = allow_metadata_inventory_take, +}) diff --git a/mods/default/init.lua b/mods/default/init.lua new file mode 100644 index 0000000..9e1bb81 --- /dev/null +++ b/mods/default/init.lua @@ -0,0 +1,57 @@ +-- Minetest 0.4 mod: default +-- See README.txt for licensing and other information. + +-- The API documentation in here was moved into game_api.txt + +-- Definitions made by this mod that other mods can use too +default = {} + +default.LIGHT_MAX = 14 + +-- GUI related stuff +default.gui_bg = "" +default.gui_bg_img = "" +default.gui_slots = "" + +function default.get_hotbar_bg(x, y, hotbar_count) + if hotbar_count then + hotbar_count = hotbar_count - 1 + else + hotbar_count = 7 + end + local out = "" + for i = 0, hotbar_count, 1 do + out = out .. "image[" .. x + i .. "," .. y .. ";1,1;gui_hb_bg.png]" + end + return out +end + +default.gui_survival_form = "size[8,8.5]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "list[current_player;main;0,4.25;8,1;]".. + "list[current_player;main;0,5.5;8,3;8]".. + "list[current_player;craft;1.75,0.5;3,3;]".. + "list[current_player;craftpreview;5.75,1.5;1,1;]".. + "image[4.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "listring[current_player;main]".. + "listring[current_player;craft]".. + default.get_hotbar_bg(0,4.25) + +-- Load files +local default_path = minetest.get_modpath("default") + +dofile(default_path.."/functions.lua") +dofile(default_path.."/trees.lua") +dofile(default_path.."/nodes.lua") +dofile(default_path.."/chests.lua") +dofile(default_path.."/furnace.lua") +dofile(default_path.."/torch.lua") +dofile(default_path.."/tools.lua") +dofile(default_path.."/item_entity.lua") +dofile(default_path.."/craftitems.lua") +dofile(default_path.."/crafting.lua") +dofile(default_path.."/mapgen.lua") +dofile(default_path.."/aliases.lua") +dofile(default_path.."/legacy.lua") diff --git a/mods/default/item_entity.lua b/mods/default/item_entity.lua new file mode 100644 index 0000000..2a61f08 --- /dev/null +++ b/mods/default/item_entity.lua @@ -0,0 +1,74 @@ +-- mods/default/item_entity.lua + +local builtin_item = minetest.registered_entities["__builtin:item"] + +local item = { + set_item = function(self, itemstring) + builtin_item.set_item(self, itemstring) + + local stack = ItemStack(itemstring) + local itemdef = minetest.registered_items[stack:get_name()] + if itemdef and itemdef.groups.flammable ~= 0 then + self.flammable = itemdef.groups.flammable + end + end, + + burn_up = function(self) + -- disappear in a smoke puff + self.object:remove() + local p = self.object:get_pos() + minetest.sound_play("default_item_smoke", { + pos = p, + max_hear_distance = 8, + }) + minetest.add_particlespawner({ + amount = 3, + time = 0.1, + minpos = {x = p.x - 0.1, y = p.y + 0.1, z = p.z - 0.1 }, + maxpos = {x = p.x + 0.1, y = p.y + 0.2, z = p.z + 0.1 }, + minvel = {x = 0, y = 2.5, z = 0}, + maxvel = {x = 0, y = 2.5, z = 0}, + minacc = {x = -0.15, y = -0.02, z = -0.15}, + maxacc = {x = 0.15, y = -0.01, z = 0.15}, + minexptime = 4, + maxexptime = 6, + minsize = 5, + maxsize = 5, + collisiondetection = true, + texture = "default_item_smoke.png" + }) + end, + + on_step = function(self, dtime) + builtin_item.on_step(self, dtime) + + if self.flammable then + -- flammable, check for igniters + self.ignite_timer = (self.ignite_timer or 0) + dtime + if self.ignite_timer > 10 then + self.ignite_timer = 0 + + local node = minetest.get_node_or_nil(self.object:get_pos()) + if not node then + return + end + + -- Immediately burn up flammable items in lava + if minetest.get_item_group(node.name, "lava") > 0 then + self:burn_up() + else + -- otherwise there'll be a chance based on its igniter value + local burn_chance = self.flammable + * minetest.get_item_group(node.name, "igniter") + if burn_chance > 0 and math.random(0, burn_chance) ~= 0 then + self:burn_up() + end + end + end + end + end, +} + +-- set defined item as new __builtin:item, with the old one as fallback table +setmetatable(item, builtin_item) +minetest.register_entity(":__builtin:item", item) diff --git a/mods/default/legacy.lua b/mods/default/legacy.lua new file mode 100644 index 0000000..123fcd5 --- /dev/null +++ b/mods/default/legacy.lua @@ -0,0 +1,46 @@ +-- mods/default/legacy.lua + +-- Horrible stuff to support old code registering falling nodes +-- Don't use this and never do what this does, it's completely wrong! +-- (More specifically, the client and the C++ code doesn't get the group) +function default.register_falling_node(nodename, texture) + minetest.log("error", debug.traceback()) + minetest.log('error', "WARNING: default.register_falling_node is deprecated") + if minetest.registered_nodes[nodename] then + minetest.registered_nodes[nodename].groups.falling_node = 1 + end +end + +function default.spawn_falling_node(p, nodename) + spawn_falling_node(p, nodename) +end + +-- Liquids +WATER_ALPHA = minetest.registered_nodes["default:water_source"].alpha +WATER_VISC = minetest.registered_nodes["default:water_source"].liquid_viscosity +LAVA_VISC = minetest.registered_nodes["default:lava_source"].liquid_viscosity +LIGHT_MAX = default.LIGHT_MAX + +-- Formspecs +default.gui_suvival_form = default.gui_survival_form + +-- Players +if minetest.get_modpath("player_api") then + default.registered_player_models = player_api.registered_models + default.player_register_model = player_api.register_model + default.player_attached = player_api.player_attached + default.player_get_animation = player_api.get_animation + default.player_set_model = player_api.set_model + default.player_set_textures = player_api.set_textures + default.player_set_animation = player_api.set_animation +end + +-- Chests +default.register_chest = default.chest.register_chest + +-- Check for a volume intersecting protection +function default.intersects_protection(minp, maxp, player_name, interval) + minetest.log("warning", "default.intersects_protection() is " .. + "deprecated, use minetest.is_area_protected() instead.") + minetest.is_area_protected(minp, maxp, player_name, interval) +end diff --git a/mods/default/license.txt b/mods/default/license.txt new file mode 100644 index 0000000..a5ea24b --- /dev/null +++ b/mods/default/license.txt @@ -0,0 +1,155 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2011-2018 celeron55, Perttu Ahola +Copyright (C) 2011-2018 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, models and sounds) +----------------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2010-2018: + + celeron55, Perttu Ahola + Cisoun + G4JC + VanessaE + RealBadAngel + Calinou + MirceaKitsune + Jordach + PilzAdam + jojoa1997 + InfinityProject + Splizard + Zeg9 + paramat + BlockMen + sofar + Neuromancer + Gambit + asl97 + KevDoy + Mito551 + GreenXenith + kaeza + kilbith + tobyplowy + CloudyProton + TumeniNodes + Mossmanikin + random-geek + +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/ + +----------------------- + +Attribution 3.0 Unported (CC BY 3.0) + +Copyright (C) 2009 cmusounddesign +Copyright (C) 2010 Tomlija +Copyright (C) 2010 lsprice +Copyright (C) 2014 sonictechtonic +Copyright (C) 2015 yadronoff +Copyright (C) 2007 HerbertBoland +Copyright (C) 2006 AGFX + +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. + +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/3.0/ + +----------------------- + +CC0 1.0 Universal (CC0 1.0) Public Domain Dedication + +Iwan Gabovitch +Ottomaani138 +Ogrebane +blukotek +Sevin7 +Yoyodaman234 +Ryding + +No Copyright + +The person who associated a work with this deed has dedicated the work to the +public domain by waiving all of his or her rights to the work worldwide under +copyright law, including all related and neighboring rights, to the extent +allowed by law. + +You can copy, modify, distribute and perform the work, even for commercial +purposes, all without asking permission. See Other Information below. + +Other Information: + +In no way are the patent or trademark rights of any person affected by CC0, nor +are the rights that other persons may have in the work or in how the work is +used, such as publicity or privacy rights. + +Unless expressly stated otherwise, the person who associated a work with this +deed makes no warranties about the work, and disclaims liability for all uses +of the work, to the fullest extent permitted by applicable law. + +When using or citing the work, you should not imply endorsement by the author +or the affirmer. + +For more details: +https://creativecommons.org/publicdomain/zero/1.0/ diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua new file mode 100644 index 0000000..b92e12e --- /dev/null +++ b/mods/default/mapgen.lua @@ -0,0 +1,2272 @@ +-- +-- Aliases for map generators +-- + +minetest.register_alias("mapgen_stone", "default:stone") +minetest.register_alias("mapgen_dirt", "default:dirt") +minetest.register_alias("mapgen_dirt_with_grass", "default:dirt_with_grass") +minetest.register_alias("mapgen_sand", "default:sand") +minetest.register_alias("mapgen_water_source", "default:water_source") +minetest.register_alias("mapgen_river_water_source", "default:river_water_source") +minetest.register_alias("mapgen_lava_source", "default:lava_source") +minetest.register_alias("mapgen_gravel", "default:gravel") +minetest.register_alias("mapgen_desert_stone", "default:desert_stone") +minetest.register_alias("mapgen_desert_sand", "default:desert_sand") +minetest.register_alias("mapgen_dirt_with_snow", "default:dirt_with_snow") +minetest.register_alias("mapgen_snowblock", "default:snowblock") +minetest.register_alias("mapgen_snow", "default:snow") +minetest.register_alias("mapgen_ice", "default:ice") +minetest.register_alias("mapgen_sandstone", "default:sandstone") + +-- Flora + +minetest.register_alias("mapgen_tree", "default:tree") +minetest.register_alias("mapgen_leaves", "default:leaves") +minetest.register_alias("mapgen_apple", "default:apple") +minetest.register_alias("mapgen_jungletree", "default:jungletree") +minetest.register_alias("mapgen_jungleleaves", "default:jungleleaves") +minetest.register_alias("mapgen_junglegrass", "default:junglegrass") +minetest.register_alias("mapgen_pine_tree", "default:pine_tree") +minetest.register_alias("mapgen_pine_needles", "default:pine_needles") + +-- Dungeons + +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_sandstone_block", "stairs:stair_sandstone_block") + + +-- +-- Register ores +-- + +-- Mgv6 + +function default.register_mgv6_ores() + + -- Blob ore + -- These first to avoid other ores in blobs + + -- Clay + -- This first to avoid clay in sand blobs + + minetest.register_ore({ + ore_type = "blob", + ore = "default:clay", + wherein = {"default:sand"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 0, + y_min = -15, + 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 + }, + }) + + -- Sand + + minetest.register_ore({ + ore_type = "blob", + ore = "default:sand", + wherein = {"default:stone", "default:desert_stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 0, + y_min = -31, + 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 + }, + }) + + -- Dirt + + minetest.register_ore({ + ore_type = "blob", + ore = "default:dirt", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 31000, + y_min = -31, + 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 + }, + }) + + -- Gravel + + minetest.register_ore({ + ore_type = "blob", + ore = "default:gravel", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 31000, + y_min = -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 + }, + }) + + -- Scatter ores + + -- Coal + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 8 * 8 * 8, + clust_num_ores = 9, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 8 * 8 * 8, + clust_num_ores = 8, + clust_size = 3, + y_max = 64, + y_min = -31000, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 24 * 24 * 24, + clust_num_ores = 27, + clust_size = 6, + y_max = 0, + y_min = -31000, + }) + + -- Iron + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 12, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 7 * 7 * 7, + clust_num_ores = 5, + clust_size = 3, + y_max = 0, + y_min = -31000, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 24 * 24 * 24, + clust_num_ores = 27, + clust_size = 6, + y_max = -64, + y_min = -31000, + }) + + -- Copper + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 12 * 12 * 12, + clust_num_ores = 4, + clust_size = 3, + y_max = -16, + y_min = -63, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 5, + clust_size = 3, + y_max = -64, + y_min = -31000, + }) + + -- 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_max = 31000, + y_min = 1025, + }) + + 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_max = -32, + y_min = -127, + }) + + 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_max = -128, + y_min = -31000, + }) + + -- Gold + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 13 * 13 * 13, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 3, + clust_size = 2, + y_max = -64, + y_min = -255, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 13 * 13 * 13, + clust_num_ores = 5, + clust_size = 3, + y_max = -256, + y_min = -31000, + }) + + -- Mese crystal + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 14 * 14 * 14, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 18 * 18 * 18, + clust_num_ores = 3, + clust_size = 2, + y_max = -64, + y_min = -255, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 14 * 14 * 14, + clust_num_ores = 5, + clust_size = 3, + y_max = -256, + y_min = -31000, + }) + + -- Diamond + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 4, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 17 * 17 * 17, + clust_num_ores = 4, + clust_size = 3, + y_max = -128, + y_min = -255, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 4, + clust_size = 3, + y_max = -256, + y_min = -31000, + }) + + -- Mese block + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:mese", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:mese", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_max = -1024, + y_min = -31000, + }) +end + + +-- All mapgens except mgv6 + +function default.register_ores() + + -- Stratum ores. + -- These obviously first. + + -- Silver sandstone + + minetest.register_ore({ + ore_type = "stratum", + ore = "default:silver_sandstone", + wherein = {"default:stone"}, + clust_scarcity = 1, + y_max = 46, + y_min = 10, + noise_params = { + offset = 28, + scale = 16, + spread = {x = 128, y = 128, z = 128}, + seed = 90122, + octaves = 1, + }, + stratum_thickness = 4, + biomes = {"cold_desert"}, + }) + + minetest.register_ore({ + ore_type = "stratum", + ore = "default:silver_sandstone", + wherein = {"default:stone"}, + clust_scarcity = 1, + y_max = 42, + y_min = 6, + noise_params = { + offset = 24, + scale = 16, + spread = {x = 128, y = 128, z = 128}, + seed = 90122, + octaves = 1, + }, + stratum_thickness = 2, + biomes = {"cold_desert"}, + }) + + -- Desert sandstone + + minetest.register_ore({ + ore_type = "stratum", + ore = "default:desert_sandstone", + wherein = {"default:desert_stone"}, + clust_scarcity = 1, + y_max = 46, + y_min = 10, + noise_params = { + offset = 28, + scale = 16, + spread = {x = 128, y = 128, z = 128}, + seed = 90122, + octaves = 1, + }, + stratum_thickness = 4, + biomes = {"desert"}, + }) + + minetest.register_ore({ + ore_type = "stratum", + ore = "default:desert_sandstone", + wherein = {"default:desert_stone"}, + clust_scarcity = 1, + y_max = 42, + y_min = 6, + noise_params = { + offset = 24, + scale = 16, + spread = {x = 128, y = 128, z = 128}, + seed = 90122, + octaves = 1, + }, + stratum_thickness = 2, + biomes = {"desert"}, + }) + + -- Sandstone + + minetest.register_ore({ + ore_type = "stratum", + ore = "default:sandstone", + wherein = {"default:desert_stone"}, + clust_scarcity = 1, + y_max = 39, + y_min = 3, + noise_params = { + offset = 21, + scale = 16, + spread = {x = 128, y = 128, z = 128}, + seed = 90122, + octaves = 1, + }, + stratum_thickness = 2, + biomes = {"desert"}, + }) + + -- Blob ore. + -- These before scatter ores to avoid other ores in blobs. + + -- Clay + + minetest.register_ore({ + ore_type = "blob", + ore = "default:clay", + wherein = {"default:sand"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 0, + y_min = -15, + 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_max = 31000, + y_min = -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_coniferous_forest", "floatland_coniferous_forest_ocean"} + }) + + -- Dirt + + minetest.register_ore({ + ore_type = "blob", + ore = "default:dirt", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 31000, + y_min = -31, + 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_coniferous_forest"} + }) + + -- Gravel + + minetest.register_ore({ + ore_type = "blob", + ore = "default:gravel", + wherein = {"default:stone"}, + clust_scarcity = 16 * 16 * 16, + clust_size = 5, + y_max = 31000, + y_min = -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_coniferous_forest", "floatland_coniferous_forest_ocean"} + }) + + -- Scatter ores + + -- Coal + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 8 * 8 * 8, + clust_num_ores = 9, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 8 * 8 * 8, + clust_num_ores = 8, + clust_size = 3, + y_max = 64, + y_min = -127, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_coal", + wherein = "default:stone", + clust_scarcity = 12 * 12 * 12, + clust_num_ores = 30, + clust_size = 5, + y_max = -128, + y_min = -31000, + }) + + -- 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_max = 31000, + y_min = 1025, + }) + + 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_max = -64, + y_min = -127, + }) + + 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_max = -128, + y_min = -31000, + }) + + -- Copper + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 12 * 12 * 12, + clust_num_ores = 4, + clust_size = 3, + y_max = -64, + y_min = -127, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_copper", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 5, + clust_size = 3, + y_max = -128, + y_min = -31000, + }) + + -- Iron + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 9 * 9 * 9, + clust_num_ores = 12, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 7 * 7 * 7, + clust_num_ores = 5, + clust_size = 3, + y_max = -128, + y_min = -255, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_iron", + wherein = "default:stone", + clust_scarcity = 12 * 12 * 12, + clust_num_ores = 29, + clust_size = 5, + y_max = -256, + y_min = -31000, + }) + + -- Gold + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 13 * 13 * 13, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 3, + clust_size = 2, + y_max = -256, + y_min = -511, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_gold", + wherein = "default:stone", + clust_scarcity = 13 * 13 * 13, + clust_num_ores = 5, + clust_size = 3, + y_max = -512, + y_min = -31000, + }) + + -- Mese crystal + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 14 * 14 * 14, + clust_num_ores = 5, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 18 * 18 * 18, + clust_num_ores = 3, + clust_size = 2, + y_max = -512, + y_min = -1023, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_mese", + wherein = "default:stone", + clust_scarcity = 14 * 14 * 14, + clust_num_ores = 5, + clust_size = 3, + y_max = -1024, + y_min = -31000, + }) + + -- Diamond + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 4, + clust_size = 3, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 17 * 17 * 17, + clust_num_ores = 4, + clust_size = 3, + y_max = -1024, + y_min = -2047, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:stone_with_diamond", + wherein = "default:stone", + clust_scarcity = 15 * 15 * 15, + clust_num_ores = 4, + clust_size = 3, + y_max = -2048, + y_min = -31000, + }) + + -- Mese block + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:mese", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_max = 31000, + y_min = 1025, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:mese", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 3, + clust_size = 2, + y_max = -2048, + y_min = -4095, + }) + + minetest.register_ore({ + ore_type = "scatter", + ore = "default:mese", + wherein = "default:stone", + clust_scarcity = 28 * 28 * 28, + clust_num_ores = 5, + clust_size = 3, + y_max = -4096, + y_min = -31000, + }) +end + + +-- +-- Register biomes +-- + +-- All mapgens except mgv6 + +function default.register_biomes(upper_limit) + + -- Icesheet + + minetest.register_biome({ + name = "icesheet", + node_dust = "default:snowblock", + node_top = "default:snowblock", + depth_top = 1, + node_filler = "default:snowblock", + depth_filler = 3, + node_stone = "default:cave_ice", + node_water_top = "default:ice", + depth_water_top = 10, + node_river_water = "default:ice", + node_riverbed = "default:gravel", + depth_riverbed = 2, + y_max = upper_limit, + y_min = -8, + heat_point = 0, + humidity_point = 73, + }) + + minetest.register_biome({ + name = "icesheet_ocean", + node_dust = "default:snowblock", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_water_top = "default:ice", + depth_water_top = 10, + y_max = -9, + y_min = -112, + heat_point = 0, + humidity_point = 73, + }) + + -- Tundra + + minetest.register_biome({ + name = "tundra_highland", + node_dust = "default:snow", + node_riverbed = "default:gravel", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 47, + heat_point = 0, + humidity_point = 40, + }) + + minetest.register_biome({ + name = "tundra", + node_top = "default:permafrost_with_stones", + depth_top = 1, + node_filler = "default:permafrost", + depth_filler = 1, + node_riverbed = "default:gravel", + depth_riverbed = 2, + vertical_blend = 4, + y_max = 46, + y_min = 2, + heat_point = 0, + humidity_point = 40, + }) + + minetest.register_biome({ + name = "tundra_beach", + node_top = "default:gravel", + depth_top = 1, + node_filler = "default:gravel", + depth_filler = 2, + node_riverbed = "default:gravel", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 1, + y_min = -3, + heat_point = 0, + humidity_point = 40, + }) + + minetest.register_biome({ + name = "tundra_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:gravel", + depth_riverbed = 2, + vertical_blend = 1, + y_max = -4, + y_min = -112, + heat_point = 0, + humidity_point = 40, + }) + + -- Taiga + + minetest.register_biome({ + name = "taiga", + node_dust = "default:snow", + node_top = "default:dirt_with_snow", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 4, + heat_point = 25, + humidity_point = 70, + }) + + minetest.register_biome({ + name = "taiga_ocean", + node_dust = "default:snow", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 3, + y_min = -112, + heat_point = 25, + humidity_point = 70, + }) + + -- Snowy grassland + + minetest.register_biome({ + name = "snowy_grassland", + node_dust = "default:snow", + node_top = "default:dirt_with_snow", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 4, + heat_point = 20, + humidity_point = 35, + }) + + minetest.register_biome({ + name = "snowy_grassland_ocean", + node_dust = "default:snow", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 3, + y_min = -112, + heat_point = 20, + humidity_point = 35, + }) + + -- Grassland + + minetest.register_biome({ + name = "grassland", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 6, + heat_point = 50, + humidity_point = 35, + }) + + minetest.register_biome({ + name = "grassland_dunes", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 2, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 5, + y_min = 4, + heat_point = 50, + humidity_point = 35, + }) + + minetest.register_biome({ + name = "grassland_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 3, + y_min = -112, + heat_point = 50, + humidity_point = 35, + }) + + -- Coniferous forest + + minetest.register_biome({ + name = "coniferous_forest", + node_top = "default:dirt_with_coniferous_litter", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 6, + heat_point = 45, + humidity_point = 70, + }) + + minetest.register_biome({ + name = "coniferous_forest_dunes", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 5, + y_min = 4, + heat_point = 45, + humidity_point = 70, + }) + + minetest.register_biome({ + name = "coniferous_forest_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 3, + y_min = -112, + heat_point = 45, + humidity_point = 70, + }) + + -- Deciduous forest + + minetest.register_biome({ + name = "deciduous_forest", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 1, + heat_point = 60, + humidity_point = 68, + }) + + minetest.register_biome({ + name = "deciduous_forest_shore", + node_top = "default:dirt", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 0, + y_min = -1, + heat_point = 60, + humidity_point = 68, + }) + + minetest.register_biome({ + name = "deciduous_forest_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = -2, + y_min = -112, + heat_point = 60, + humidity_point = 68, + }) + + -- Desert + + minetest.register_biome({ + name = "desert", + node_top = "default:desert_sand", + depth_top = 1, + node_filler = "default:desert_sand", + depth_filler = 1, + node_stone = "default:desert_stone", + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 4, + heat_point = 92, + humidity_point = 16, + }) + + minetest.register_biome({ + name = "desert_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_stone = "default:desert_stone", + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 3, + y_min = -112, + heat_point = 92, + humidity_point = 16, + }) + + -- Sandstone desert + + minetest.register_biome({ + name = "sandstone_desert", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 1, + node_stone = "default:sandstone", + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 4, + heat_point = 60, + humidity_point = 0, + }) + + minetest.register_biome({ + name = "sandstone_desert_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_stone = "default:sandstone", + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 3, + y_min = -112, + heat_point = 60, + humidity_point = 0, + }) + + -- Cold desert + + minetest.register_biome({ + name = "cold_desert", + node_top = "default:silver_sand", + depth_top = 1, + node_filler = "default:silver_sand", + depth_filler = 1, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 4, + heat_point = 40, + humidity_point = 0, + }) + + minetest.register_biome({ + name = "cold_desert_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = 3, + y_min = -112, + heat_point = 40, + humidity_point = 0, + }) + + -- Savanna + + minetest.register_biome({ + name = "savanna", + node_top = "default:dirt_with_dry_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 1, + heat_point = 89, + humidity_point = 42, + }) + + minetest.register_biome({ + name = "savanna_shore", + node_top = "default:dirt", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 0, + y_min = -1, + heat_point = 89, + humidity_point = 42, + }) + + minetest.register_biome({ + name = "savanna_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = -2, + y_min = -112, + heat_point = 89, + humidity_point = 42, + }) + + -- Rainforest + + minetest.register_biome({ + name = "rainforest", + node_top = "default:dirt_with_rainforest_litter", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = upper_limit, + y_min = 1, + heat_point = 86, + humidity_point = 65, + }) + + minetest.register_biome({ + name = "rainforest_swamp", + node_top = "default:dirt", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + y_max = 0, + y_min = -1, + heat_point = 86, + humidity_point = 65, + }) + + minetest.register_biome({ + name = "rainforest_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + node_riverbed = "default:sand", + depth_riverbed = 2, + vertical_blend = 1, + y_max = -2, + y_min = -112, + heat_point = 86, + humidity_point = 65, + }) + + -- Underground + + minetest.register_biome({ + name = "underground", + y_max = -113, + y_min = -31000, + heat_point = 50, + humidity_point = 50, + }) +end + + +-- Biomes for floatlands + +-- TODO Temporary simple biomes to be replaced by special floatland biomes later. + +function default.register_floatland_biomes(floatland_level, shadow_limit) + + minetest.register_biome({ + name = "floatland_grassland", + node_top = "default:dirt_with_grass", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 1, + y_max = 31000, + y_min = floatland_level + 2, + heat_point = 50, + humidity_point = 25, + }) + + minetest.register_biome({ + name = "floatland_coniferous_forest", + node_top = "default:dirt_with_coniferous_litter", + depth_top = 1, + node_filler = "default:dirt", + depth_filler = 3, + y_max = 31000, + y_min = floatland_level + 2, + heat_point = 50, + humidity_point = 75, + }) + + minetest.register_biome({ + name = "floatland_ocean", + node_top = "default:sand", + depth_top = 1, + node_filler = "default:sand", + depth_filler = 3, + y_max = floatland_level + 1, + y_min = shadow_limit, + heat_point = 50, + humidity_point = 50, + }) +end + + +-- +-- Register decorations +-- + +-- Mgv6 + +function default.register_mgv6_decorations() + + -- Papyrus + + minetest.register_decoration({ + name = "default:papyrus", + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = -0.3, + scale = 0.7, + spread = {x = 100, y = 100, z = 100}, + seed = 354, + octaves = 3, + persist = 0.7 + }, + y_max = 1, + y_min = 1, + decoration = "default:papyrus", + height = 2, + height_max = 4, + spawn_by = "default:water_source", + num_spawn_by = 1, + }) + + -- Cacti + + minetest.register_decoration({ + name = "default:cactus", + deco_type = "simple", + place_on = {"default:desert_sand"}, + sidelen = 16, + noise_params = { + offset = -0.012, + scale = 0.024, + spread = {x = 100, y = 100, z = 100}, + seed = 230, + octaves = 3, + persist = 0.6 + }, + y_max = 30, + y_min = 1, + decoration = "default:cactus", + height = 3, + height_max = 4, + }) + + -- Long grasses + + for length = 1, 5 do + minetest.register_decoration({ + name = "default:grass_"..length, + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.007, + spread = {x = 100, y = 100, z = 100}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + y_max = 30, + y_min = 1, + decoration = "default:grass_"..length, + }) + end + + -- Dry shrubs + + minetest.register_decoration({ + name = "default:dry_shrub", + deco_type = "simple", + place_on = {"default:desert_sand", "default:dirt_with_snow"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.035, + spread = {x = 100, y = 100, z = 100}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + y_max = 30, + y_min = 1, + decoration = "default:dry_shrub", + param2 = 4, + }) +end + + +-- All mapgens except mgv6 + +local function register_grass_decoration(offset, scale, length) + minetest.register_decoration({ + name = "default:grass_" .. length, + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = offset, + scale = scale, + spread = {x = 200, y = 200, z = 200}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + biomes = {"grassland", "deciduous_forest", "floatland_grassland"}, + y_max = 31000, + y_min = 1, + decoration = "default:grass_" .. length, + }) +end + +local function register_dry_grass_decoration(offset, scale, length) + minetest.register_decoration({ + name = "default:dry_grass_" .. length, + deco_type = "simple", + place_on = {"default:dirt_with_dry_grass"}, + sidelen = 16, + noise_params = { + offset = offset, + scale = scale, + spread = {x = 200, y = 200, z = 200}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + biomes = {"savanna"}, + y_max = 31000, + y_min = 1, + decoration = "default:dry_grass_" .. length, + }) +end + +local function register_fern_decoration(seed, length) + minetest.register_decoration({ + name = "default:fern_" .. length, + deco_type = "simple", + place_on = {"default:dirt_with_coniferous_litter"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.2, + spread = {x = 100, y = 100, z = 100}, + seed = seed, + octaves = 3, + persist = 0.7 + }, + biomes = {"coniferous_forest", "floatland_coniferous_forest"}, + y_max = 31000, + y_min = 6, + decoration = "default:fern_" .. length, + }) +end + + +function default.register_decorations() + + -- Apple tree and log + + minetest.register_decoration({ + name = "default:apple_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0.024, + scale = 0.015, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"deciduous_forest"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/apple_tree.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + }) + + minetest.register_decoration({ + name = "default:apple_log", + deco_type = "schematic", + place_on = {"default:dirt_with_grass"}, + place_offset_y = 1, + sidelen = 16, + noise_params = { + offset = 0.0012, + scale = 0.0007, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"deciduous_forest"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/apple_log.mts", + flags = "place_center_x", + rotation = "random", + spawn_by = "default:dirt_with_grass", + num_spawn_by = 8, + }) + + -- Emergent jungle tree + -- Due to 32 node height, altitude is limited and prescence depends on chunksize + + local chunksize = tonumber(minetest.get_mapgen_setting("chunksize")) + if chunksize >= 5 then + minetest.register_decoration({ + name = "default:emergent_jungle_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_rainforest_litter"}, + sidelen = 80, + noise_params = { + offset = 0.0, + scale = 0.0025, + spread = {x = 250, y = 250, z = 250}, + seed = 2685, + octaves = 3, + persist = 0.7 + }, + biomes = {"rainforest"}, + y_max = 32, + y_min = 1, + schematic = minetest.get_modpath("default") .. + "/schematics/emergent_jungle_tree.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + place_offset_y = -4, + }) + end + + -- Jungle tree and log + + minetest.register_decoration({ + name = "default:jungle_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_rainforest_litter", "default:dirt"}, + sidelen = 80, + fill_ratio = 0.1, + biomes = {"rainforest", "rainforest_swamp"}, + y_max = 31000, + y_min = -1, + schematic = minetest.get_modpath("default") .. "/schematics/jungle_tree.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + }) + + minetest.register_decoration({ + name = "default:jungle_log", + deco_type = "schematic", + place_on = {"default:dirt_with_rainforest_litter"}, + place_offset_y = 1, + sidelen = 80, + fill_ratio = 0.005, + biomes = {"rainforest", "rainforest_swamp"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/jungle_log.mts", + flags = "place_center_x", + rotation = "random", + spawn_by = "default:dirt_with_rainforest_litter", + num_spawn_by = 8, + }) + + -- Taiga and temperate coniferous forest pine tree, small pine tree and log + + minetest.register_decoration({ + name = "default:pine_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_snow", "default:dirt_with_coniferous_litter"}, + sidelen = 16, + noise_params = { + offset = 0.010, + scale = 0.048, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"taiga", "coniferous_forest", "floatland_coniferous_forest"}, + y_max = 31000, + y_min = 4, + schematic = minetest.get_modpath("default") .. "/schematics/pine_tree.mts", + flags = "place_center_x, place_center_z", + }) + + minetest.register_decoration({ + name = "default:small_pine_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_snow", "default:dirt_with_coniferous_litter"}, + sidelen = 16, + noise_params = { + offset = 0.010, + scale = -0.048, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"taiga", "coniferous_forest", "floatland_coniferous_forest"}, + y_max = 31000, + y_min = 4, + schematic = minetest.get_modpath("default") .. "/schematics/small_pine_tree.mts", + flags = "place_center_x, place_center_z", + }) + + minetest.register_decoration({ + name = "default:pine_log", + deco_type = "schematic", + place_on = {"default:dirt_with_snow", "default:dirt_with_coniferous_litter"}, + place_offset_y = 1, + sidelen = 80, + fill_ratio = 0.0018, + biomes = {"taiga", "coniferous_forest", "floatland_coniferous_forest"}, + y_max = 31000, + y_min = 4, + schematic = minetest.get_modpath("default") .. "/schematics/pine_log.mts", + flags = "place_center_x", + rotation = "random", + spawn_by = {"default:dirt_with_snow", "default:dirt_with_coniferous_litter"}, + num_spawn_by = 8, + }) + + -- Acacia tree and log + + minetest.register_decoration({ + name = "default:acacia_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_dry_grass"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.002, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"savanna"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/acacia_tree.mts", + flags = "place_center_x, place_center_z", + rotation = "random", + }) + + minetest.register_decoration({ + name = "default:acacia_log", + deco_type = "schematic", + place_on = {"default:dirt_with_dry_grass"}, + place_offset_y = 1, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.001, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"savanna"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/acacia_log.mts", + flags = "place_center_x", + rotation = "random", + spawn_by = "default:dirt_with_dry_grass", + num_spawn_by = 8, + }) + + -- Aspen tree and log + + minetest.register_decoration({ + name = "default:aspen_tree", + deco_type = "schematic", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0.0, + scale = -0.015, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"deciduous_forest"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/aspen_tree.mts", + flags = "place_center_x, place_center_z", + }) + + minetest.register_decoration({ + name = "default:aspen_log", + deco_type = "schematic", + place_on = {"default:dirt_with_grass"}, + place_offset_y = 1, + sidelen = 16, + noise_params = { + offset = 0.0, + scale = -0.0008, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"deciduous_forest"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/aspen_log.mts", + flags = "place_center_x", + rotation = "random", + spawn_by = "default:dirt_with_grass", + num_spawn_by = 8, + }) + + -- Large cactus + + minetest.register_decoration({ + name = "default:large_cactus", + deco_type = "schematic", + place_on = {"default:desert_sand"}, + sidelen = 16, + noise_params = { + offset = -0.0003, + scale = 0.0009, + spread = {x = 200, y = 200, z = 200}, + seed = 230, + octaves = 3, + persist = 0.6 + }, + biomes = {"desert"}, + y_max = 31000, + y_min = 4, + schematic = minetest.get_modpath("default") .. "/schematics/large_cactus.mts", + flags = "place_center_x", + rotation = "random", + }) + + -- Cactus + + minetest.register_decoration({ + name = "default:cactus", + deco_type = "simple", + place_on = {"default:desert_sand"}, + sidelen = 16, + noise_params = { + offset = -0.0003, + scale = 0.0009, + spread = {x = 200, y = 200, z = 200}, + seed = 230, + octaves = 3, + persist = 0.6 + }, + biomes = {"desert"}, + y_max = 31000, + y_min = 4, + decoration = "default:cactus", + height = 2, + height_max = 5, + }) + + -- Papyrus + + minetest.register_decoration({ + name = "default:papyrus", + deco_type = "schematic", + place_on = {"default:dirt"}, + sidelen = 16, + noise_params = { + offset = -0.3, + scale = 0.7, + spread = {x = 200, y = 200, z = 200}, + seed = 354, + octaves = 3, + persist = 0.7 + }, + biomes = {"savanna_shore"}, + y_max = 0, + y_min = 0, + schematic = minetest.get_modpath("default") .. "/schematics/papyrus.mts", + }) + + -- Bush + + minetest.register_decoration({ + name = "default:bush", + deco_type = "schematic", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = -0.004, + scale = 0.01, + spread = {x = 100, y = 100, z = 100}, + seed = 137, + octaves = 3, + persist = 0.7, + }, + biomes = {"grassland", "deciduous_forest", + "floatland_grassland"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/bush.mts", + flags = "place_center_x, place_center_z", + }) + + -- Blueberry bush + + minetest.register_decoration({ + name = "default:blueberry_bush", + deco_type = "schematic", + place_on = {"default:dirt_with_grass", "default:dirt_with_snow"}, + sidelen = 16, + noise_params = { + offset = -0.004, + scale = 0.01, + spread = {x = 100, y = 100, z = 100}, + seed = 697, + octaves = 3, + persist = 0.7, + }, + biomes = {"grassland", "snowy_grassland"}, + y_max = 31000, + y_min = 1, + place_offset_y = 1, + schematic = minetest.get_modpath("default") .. "/schematics/blueberry_bush.mts", + flags = "place_center_x, place_center_z", + }) + + -- Acacia bush + + minetest.register_decoration({ + name = "default:acacia_bush", + deco_type = "schematic", + place_on = {"default:dirt_with_dry_grass"}, + sidelen = 16, + noise_params = { + offset = -0.004, + scale = 0.01, + spread = {x = 100, y = 100, z = 100}, + seed = 90155, + octaves = 3, + persist = 0.7, + }, + biomes = {"savanna"}, + y_max = 31000, + y_min = 1, + schematic = minetest.get_modpath("default") .. "/schematics/acacia_bush.mts", + flags = "place_center_x, place_center_z", + }) + + -- Pine bush + + minetest.register_decoration({ + name = "default:pine_bush", + deco_type = "schematic", + place_on = {"default:dirt_with_snow"}, + sidelen = 16, + noise_params = { + offset = -0.004, + scale = 0.01, + spread = {x = 100, y = 100, z = 100}, + seed = 137, + octaves = 3, + persist = 0.7, + }, + biomes = {"taiga", "snowy_grassland"}, + y_max = 31000, + y_min = 4, + schematic = minetest.get_modpath("default") .. "/schematics/pine_bush.mts", + flags = "place_center_x, place_center_z", + }) + + -- Grasses + + register_grass_decoration(-0.03, 0.09, 5) + register_grass_decoration(-0.015, 0.075, 4) + register_grass_decoration(0, 0.06, 3) + register_grass_decoration(0.015, 0.045, 2) + register_grass_decoration(0.03, 0.03, 1) + + -- Dry grasses + + register_dry_grass_decoration(0.01, 0.05, 5) + register_dry_grass_decoration(0.03, 0.03, 4) + register_dry_grass_decoration(0.05, 0.01, 3) + register_dry_grass_decoration(0.07, -0.01, 2) + register_dry_grass_decoration(0.09, -0.03, 1) + + -- Ferns + + register_fern_decoration(14936, 3) + register_fern_decoration(801, 2) + register_fern_decoration(5, 1) + + -- Junglegrass + + minetest.register_decoration({ + name = "default:junglegrass", + deco_type = "simple", + place_on = {"default:dirt_with_rainforest_litter"}, + sidelen = 80, + fill_ratio = 0.1, + biomes = {"rainforest"}, + y_max = 31000, + y_min = 1, + decoration = "default:junglegrass", + }) + + -- Dry shrub + + minetest.register_decoration({ + name = "default:dry_shrub", + deco_type = "simple", + place_on = {"default:desert_sand", + "default:sand", "default:silver_sand"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.02, + spread = {x = 200, y = 200, z = 200}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + biomes = {"desert", "sandstone_desert", "cold_desert"}, + y_max = 31000, + y_min = 2, + decoration = "default:dry_shrub", + param2 = 4, + }) + + -- Marram grass + + minetest.register_decoration({ + name = "default:marram_grass", + deco_type = "simple", + place_on = {"default:sand"}, + sidelen = 4, + noise_params = { + offset = -0.4, + scale = 3.0, + spread = {x = 16, y = 16, z = 16}, + seed = 513337, + octaves = 1, + persist = 0.5, + flags = "absvalue" + }, + biomes = {"coniferous_forest_dunes", "grassland_dunes"}, + y_max = 6, + y_min = 4, + decoration = { + "default:marram_grass_1", + "default:marram_grass_2", + "default:marram_grass_3", + }, + }) + + -- Tundra moss + + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:permafrost_with_stones"}, + sidelen = 4, + noise_params = { + offset = -0.8, + scale = 2.0, + spread = {x = 100, y = 100, z = 100}, + seed = 53995, + octaves = 3, + persist = 1.0 + }, + biomes = {"tundra"}, + y_max = 50, + y_min = 2, + decoration = "default:permafrost_with_moss", + place_offset_y = -1, + flags = "force_placement", + }) + + -- Tundra patchy snow + + minetest.register_decoration({ + deco_type = "simple", + place_on = { + "default:permafrost_with_moss", + "default:permafrost_with_stones", + "default:stone", + "default:gravel" + }, + sidelen = 4, + noise_params = { + offset = 0, + scale = 1.0, + spread = {x = 100, y = 100, z = 100}, + seed = 172555, + octaves = 3, + persist = 1.0 + }, + biomes = {"tundra", "tundra_beach"}, + y_max = 50, + y_min = 1, + decoration = "default:snow", + }) + + -- Coral reef + + minetest.register_decoration({ + name = "default:corals", + deco_type = "simple", + place_on = {"default:sand"}, + place_offset_y = -1, + sidelen = 4, + noise_params = { + offset = -4, + scale = 4, + spread = {x = 50, y = 50, z = 50}, + seed = 7013, + octaves = 3, + persist = 0.7, + }, + biomes = { + "desert_ocean", + "savanna_ocean", + "rainforest_ocean", + }, + y_max = -2, + y_min = -8, + flags = "force_placement", + decoration = { + "default:coral_green", "default:coral_pink", + "default:coral_cyan", "default:coral_brown", + "default:coral_orange", "default:coral_skeleton", + }, + }) + + -- Kelp + + minetest.register_decoration({ + name = "default:kelp", + deco_type = "simple", + place_on = {"default:sand"}, + place_offset_y = -1, + sidelen = 16, + noise_params = { + offset = -0.04, + scale = 0.1, + spread = {x = 200, y = 200, z = 200}, + seed = 87112, + octaves = 3, + persist = 0.7 + }, + biomes = { + "taiga_ocean", + "snowy_grassland_ocean", + "grassland_ocean", + "coniferous_forest_ocean", + "deciduous_forest_ocean", + "sandstone_desert_ocean", + "cold_desert_ocean"}, + y_max = -5, + y_min = -10, + flags = "force_placement", + decoration = "default:sand_with_kelp", + param2 = 48, + param2_max = 96, + }) +end + + +-- +-- 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, caverns" +local captures_float = string.match(mgv7_spflags, "floatlands") +local captures_nofloat = string.match(mgv7_spflags, "nofloatlands") + +-- Get setting or default +-- Make global for mods to use to register floatland biomes +default.mgv7_floatland_level = + minetest.get_mapgen_setting("mgv7_floatland_level") or 1280 +default.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_ores() + default.register_mgv6_decorations() +-- Need to check for 'nofloatlands' because that contains +-- 'floatlands' which makes the second condition true. +elseif mg_name == "v7" and + captures_float == "floatlands" and + captures_nofloat ~= "nofloatlands" then + -- Mgv7 with floatlands and floatland biomes + default.register_biomes(default.mgv7_shadow_limit - 1) + default.register_floatland_biomes( + default.mgv7_floatland_level, default.mgv7_shadow_limit) + default.register_ores() + default.register_decorations() +else + default.register_biomes(31000) + 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 0000000..72ba175 --- /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/models/torch_ceiling.obj b/mods/default/models/torch_ceiling.obj new file mode 100644 index 0000000..ea51f3c --- /dev/null +++ b/mods/default/models/torch_ceiling.obj @@ -0,0 +1,58 @@ +# Blender v2.77 (sub 0) OBJ File: 'torch_ceiling.blend' +# www.blender.org +mtllib torch_ceiling.mtl +o Cube_Cube.001 +v -0.062469 -0.047331 0.068152 +v -0.062469 -0.559515 -0.164388 +v -0.062469 0.004344 -0.045667 +v -0.062469 -0.507839 -0.278206 +v 0.062531 -0.047331 0.068152 +v 0.062531 -0.559515 -0.164388 +v 0.062531 0.004344 -0.045667 +v 0.062531 -0.507839 -0.278206 +v 0.353584 0.040000 0.363553 +v 0.353584 -0.397500 0.363553 +v -0.353522 0.040000 -0.343553 +v -0.353522 -0.397500 -0.343553 +v 0.353584 0.040000 -0.343553 +v -0.353522 0.040000 0.363553 +v 0.353584 -0.397500 -0.343553 +v -0.353522 -0.397500 0.363553 +vt 0.5625 0.5000 +vt 0.5625 0.6250 +vt 0.4375 0.6250 +vt 0.4375 0.5000 +vt 0.4375 0.0000 +vt 0.5625 0.0000 +vt 0.5625 0.1250 +vt 0.4375 0.1250 +vt 0.5625 0.6250 +vt 0.4375 0.6250 +vt 0.4375 0.6250 +vt 0.4375 0.0000 +vt 0.5625 0.6250 +vt 0.5625 0.0000 +vt 1.0000 0.5625 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.5625 +vt 0.0000 0.5625 +vt 1.0000 0.5625 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vn 0.0000 0.9105 0.4134 +vn -0.0000 -0.4134 0.9105 +vn -1.0000 0.0000 0.0000 +vn 0.7071 0.0000 -0.7071 +vn 0.7071 0.0000 0.7071 +usemtl Material.001 +s off +f 3/1/1 1/2/1 5/3/1 7/4/1 +f 8/5/1 4/6/1 2/7/1 6/8/1 +f 3/9/2 4/6/2 8/5/2 7/10/2 +f 1/11/3 3/9/3 4/6/3 2/12/3 +f 5/13/2 1/11/2 2/12/2 6/14/2 +f 7/10/3 8/5/3 6/14/3 5/13/3 +usemtl Material.002 +f 9/15/4 10/16/4 12/17/4 11/18/4 +f 13/19/5 14/20/5 16/21/5 15/22/5 diff --git a/mods/default/models/torch_floor.obj b/mods/default/models/torch_floor.obj new file mode 100644 index 0000000..e2487ef --- /dev/null +++ b/mods/default/models/torch_floor.obj @@ -0,0 +1,50 @@ +# Blender v2.76 (sub 11) OBJ File: 'torch_floor.blend' +# www.blender.org +mtllib torch_floor.mtl +o Cube_Cube.001 +v 0.062500 0.062500 -0.062500 +v 0.062500 -0.500000 -0.062500 +v 0.062500 0.062500 0.062500 +v 0.062500 -0.500000 0.062500 +v -0.062500 0.062500 -0.062500 +v -0.062500 -0.500000 -0.062500 +v -0.062500 0.062500 0.062500 +v -0.062500 -0.500000 0.062500 +v -0.353553 -0.500000 0.353553 +v -0.353553 0.500000 0.353553 +v 0.353553 -0.500000 -0.353553 +v 0.353553 0.500000 -0.353553 +v -0.353553 -0.500000 -0.353553 +v 0.353553 -0.500000 0.353553 +v -0.353553 0.500000 -0.353553 +v 0.353553 0.500000 0.353553 +vt 0.562500 0.500000 +vt 0.562500 0.625000 +vt 0.437500 0.625000 +vt 0.437500 0.500000 +vt 0.437500 0.000000 +vt 0.562500 0.000000 +vt 0.562500 0.125000 +vt 0.437500 0.125000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 1.000000 0.000000 0.000000 +vn -0.707100 0.000000 -0.707100 +vn -0.707100 -0.000000 0.707100 +g Cube_Cube.001_Cube_Cube.001_Material.001 +usemtl Material.001 +s off +f 3/1/1 1/2/1 5/3/1 7/4/1 +f 8/5/1 4/6/1 2/7/1 6/8/1 +f 3/2/2 4/6/2 8/5/2 7/3/2 +f 1/3/3 3/2/3 4/6/3 2/5/3 +f 5/2/2 1/3/2 2/5/2 6/6/2 +f 7/3/3 8/5/3 6/6/3 5/2/3 +g Cube_Cube.001_Cube_Cube.001_Material.002 +usemtl Material.002 +f 9/9/4 10/10/4 12/11/4 11/12/4 +f 13/12/5 14/9/5 16/10/5 15/11/5 diff --git a/mods/default/models/torch_wall.obj b/mods/default/models/torch_wall.obj new file mode 100644 index 0000000..57baa9e --- /dev/null +++ b/mods/default/models/torch_wall.obj @@ -0,0 +1,64 @@ +# Blender v2.76 (sub 11) OBJ File: 'torch_wall.blend' +# www.blender.org +mtllib torch_wall.mtl +o Cube_Cube.001 +v 0.062469 -0.195248 0.023570 +v 0.062469 -0.476498 -0.463570 +v 0.062469 -0.303502 0.086070 +v 0.062469 -0.584752 -0.401070 +v -0.062531 -0.195248 0.023570 +v -0.062531 -0.476498 -0.463570 +v -0.062531 -0.303502 0.086070 +v -0.062531 -0.584752 -0.401070 +v -0.353584 -0.613553 0.022500 +v -0.353584 -0.613553 0.460000 +v 0.353522 0.093553 0.022500 +v 0.353522 0.093553 0.460000 +v -0.353584 0.093553 0.022500 +v 0.353522 -0.613553 0.022500 +v -0.353584 0.093553 0.460000 +v 0.353522 -0.613553 0.460000 +v 0.353553 0.056811 -0.121957 +v 0.353553 -0.224439 -0.609096 +v -0.353553 -0.555561 0.231596 +v -0.353553 -0.836811 -0.255543 +v -0.353553 0.056811 -0.121957 +v -0.353553 -0.224439 -0.609096 +v 0.353553 -0.555561 0.231596 +v 0.353553 -0.836811 -0.255543 +vt 0.562500 0.500000 +vt 0.562500 0.625000 +vt 0.437500 0.625000 +vt 0.437500 0.500000 +vt 0.437500 0.000000 +vt 0.562500 0.000000 +vt 0.562500 0.125000 +vt 0.437500 0.125000 +vt 0.000000 0.562500 +vt 0.000000 -0.000000 +vt 1.000000 0.000000 +vt 1.000000 0.562500 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vn -0.000000 0.500000 0.866000 +vn -0.000000 0.866000 -0.500000 +vn 1.000000 0.000000 0.000000 +vn -0.707100 0.612400 -0.353600 +vn -0.707100 -0.612400 0.353600 +vn -0.707100 0.707100 -0.000000 +vn -0.707100 -0.707100 -0.000000 +g Cube_Cube.001_Cube_Cube.001_Material.001 +usemtl Material.001 +s off +f 3/1/1 1/2/1 5/3/1 7/4/1 +f 8/5/1 4/6/1 2/7/1 6/8/1 +f 3/2/2 4/6/2 8/5/2 7/3/2 +f 1/3/3 3/2/3 4/6/3 2/5/3 +f 5/2/2 1/3/2 2/5/2 6/6/2 +f 7/3/3 8/5/3 6/6/3 5/2/3 +f 17/9/4 18/10/4 20/11/4 19/12/4 +f 21/9/5 22/10/5 24/11/5 23/12/5 +g Cube_Cube.001_Cube_Cube.001_Material.002 +usemtl Material.002 +f 9/12/6 10/13/6 12/14/6 11/9/6 +f 13/9/7 14/12/7 16/13/7 15/14/7 diff --git a/mods/default/nodes.lua b/mods/default/nodes.lua new file mode 100644 index 0000000..9827474 --- /dev/null +++ b/mods/default/nodes.lua @@ -0,0 +1,2858 @@ +-- mods/default/nodes.lua + + +--[[ Node name convention: + +Although many node names are in combined-word form, the required form for new +node names is words separated by underscores. If both forms are used in written +language (for example pinewood and pine wood) the underscore form should be used. + +--]] + + +--[[ Index: + +Stone +----- +(1. Material 2. Cobble variant 3. Brick variant 4. Modified forms) + +default:stone +default:cobble +default:stonebrick +default:stone_block +default:mossycobble + +default:desert_stone +default:desert_cobble +default:desert_stonebrick +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 +default:obsidian_block + +Soft / Non-Stone +---------------- +(1. Material 2. Modified forms) + +default:dirt +default:dirt_with_grass +default:dirt_with_grass_footsteps +default:dirt_with_dry_grass +default:dirt_with_snow +default:dirt_with_rainforest_litter +default:dirt_with_coniferous_litter + +default:permafrost +default:permafrost_with_stones +default:permafrost_with_moss + +default:sand +default:desert_sand +default:silver_sand + +default:gravel + +default:clay + +default:snow +default:snowblock +default:ice +default:cave_ice + +Trees +----- +(1. Trunk 2. Fabricated trunk 3. Leaves 4. Sapling 5. Fruits) + +default:tree +default:wood +default:leaves +default:sapling +default:apple + +default:jungletree +default:junglewood +default:jungleleaves +default:junglesapling +default:emergent_jungle_sapling + +default:pine_tree +default:pine_wood +default:pine_needles +default:pine_sapling + +default:acacia_tree +default:acacia_wood +default:acacia_leaves +default:acacia_sapling + +default:aspen_tree +default:aspen_wood +default:aspen_leaves +default:aspen_sapling + +Ores +---- +(1. In stone 2. Blocks) + +default:stone_with_coal +default:coalblock + +default:stone_with_iron +default:steelblock + +default:stone_with_copper +default:copperblock + +default:stone_with_tin +default:tinblock + +default:bronzeblock + +default:stone_with_gold +default:goldblock + +default:stone_with_mese +default:mese + +default:stone_with_diamond +default:diamondblock + +Plantlife +--------- + +default:cactus +default:papyrus +default:dry_shrub +default:junglegrass + +default:grass_1 +default:grass_2 +default:grass_3 +default:grass_4 +default:grass_5 + +default:dry_grass_1 +default:dry_grass_2 +default:dry_grass_3 +default:dry_grass_4 +default:dry_grass_5 + +default:fern_1 +default:fern_2 +default:fern_3 + +default:marram_grass_1 +default:marram_grass_2 +default:marram_grass_3 + +default:bush_stem +default:bush_leaves +default:bush_sapling +default:acacia_bush_stem +default:acacia_bush_leaves +default:acacia_bush_sapling +default:pine_bush_stem +default:pine_bush_needles +default:pine_bush_sapling +default:blueberry_bush_leaves_with_berries +default:blueberry_bush_leaves +default:blueberry_bush_sapling + +default:sand_with_kelp + +Corals +------ + +default:coral_brown +default:coral_orange +default:coral_skeleton + +Liquids +------- +(1. Source 2. Flowing) + +default:water_source +default:water_flowing + +default:river_water_source +default:river_water_flowing + +default:lava_source +default:lava_flowing + +Tools / "Advanced" crafting / Non-"natural" +------------------------------------------- + +default:bookshelf + +default:sign_wall_wood +default:sign_wall_steel + +default:ladder_wood +default:ladder_steel + +default:fence_wood +default:fence_acacia_wood +default:fence_junglewood +default:fence_pine_wood +default:fence_aspen_wood + +default:glass +default:obsidian_glass + +default:brick + +default:meselamp +default:mese_post_light + +Misc +---- + +default:cloud + +--]] + +-- +-- Stone +-- + +minetest.register_node("default:stone", { + description = "Stone", + tiles = {"default_stone.png"}, + groups = {cracky = 3, stone = 1}, + drop = 'default:cobble', + legacy_mineral = true, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:cobble", { + description = "Cobblestone", + tiles = {"default_cobble.png"}, + is_ground_content = false, + groups = {cracky = 3, stone = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:stonebrick", { + description = "Stone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_stone_brick.png"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:stone_block", { + description = "Stone Block", + tiles = {"default_stone_block.png"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:mossycobble", { + description = "Mossy Cobblestone", + tiles = {"default_mossycobble.png"}, + is_ground_content = false, + groups = {cracky = 3, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("default:desert_stone", { + description = "Desert Stone", + tiles = {"default_desert_stone.png"}, + groups = {cracky = 3, stone = 1}, + drop = 'default:desert_cobble', + legacy_mineral = true, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:desert_cobble", { + description = "Desert Cobblestone", + tiles = {"default_desert_cobble.png"}, + is_ground_content = false, + groups = {cracky = 3, stone = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:desert_stonebrick", { + description = "Desert Stone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_desert_stone_brick.png"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:desert_stone_block", { + description = "Desert Stone Block", + tiles = {"default_desert_stone_block.png"}, + is_ground_content = false, + groups = {cracky = 2, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:sandstone", { + description = "Sandstone", + tiles = {"default_sandstone.png"}, + groups = {crumbly = 1, cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:sandstonebrick", { + description = "Sandstone Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_sandstone_brick.png"}, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:sandstone_block", { + description = "Sandstone Block", + tiles = {"default_sandstone_block.png"}, + is_ground_content = false, + groups = {cracky = 2}, + 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", + tiles = {"default_obsidian.png"}, + sounds = default.node_sound_stone_defaults(), + groups = {cracky = 1, level = 2}, +}) + +minetest.register_node("default:obsidianbrick", { + description = "Obsidian Brick", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_obsidian_brick.png"}, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), + groups = {cracky = 1, level = 2}, +}) + +minetest.register_node("default:obsidian_block", { + description = "Obsidian Block", + tiles = {"default_obsidian_block.png"}, + is_ground_content = false, + sounds = default.node_sound_stone_defaults(), + groups = {cracky = 1, level = 2}, +}) + +-- +-- Soft / Non-Stone +-- + +minetest.register_node("default:dirt", { + description = "Dirt", + tiles = {"default_dirt.png"}, + groups = {crumbly = 3, soil = 1}, + sounds = default.node_sound_dirt_defaults(), +}) + +minetest.register_node("default:dirt_with_grass", { + description = "Dirt with Grass", + tiles = {"default_grass.png", "default_dirt.png", + {name = "default_dirt.png^default_grass_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.25}, + }), +}) +--[[ +minetest.register_node("default:dirt_with_grass_footsteps", { + description = "Dirt with Grass and Footsteps", + tiles = {"default_grass.png^default_footprint.png", "default_dirt.png", + {name = "default_dirt.png^default_grass_side.png", + tileable_vertical = false}}, + groups = {crumbly = 3, soil = 1, not_in_creative_inventory = 1}, + drop = 'default:dirt', + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_grass_footstep", gain = 0.25}, + }), +}) +--]] +minetest.register_node("default:dirt_with_dry_grass", { + description = "Dirt with Dry Grass", + tiles = {"default_dry_grass.png", + "default_dirt.png", + {name = "default_dirt.png^default_dry_grass_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:dirt_with_snow", { + description = "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, snowy = 1}, + drop = 'default:dirt', + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_snow_footstep", gain = 0.2}, + }), +}) + +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:dirt_with_coniferous_litter", { + description = "Dirt with Coniferous Litter", + tiles = { + "default_coniferous_litter.png", + "default_dirt.png", + {name = "default_dirt.png^default_coniferous_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:permafrost", { + description = "Permafrost", + tiles = {"default_permafrost.png"}, + groups = {cracky = 3}, + sounds = default.node_sound_dirt_defaults(), +}) + +minetest.register_node("default:permafrost_with_stones", { + description = "Permafrost with Stones", + tiles = {"default_permafrost.png^default_stones.png", + "default_permafrost.png"}, + groups = {cracky = 3}, + drop = "default:permafrost", + sounds = default.node_sound_gravel_defaults(), +}) + +minetest.register_node("default:permafrost_with_moss", { + description = "Permafrost with Moss", + tiles = {"default_moss.png", "default_permafrost.png", + {name = "default_permafrost.png^default_moss_side.png", + tileable_vertical = false}}, + groups = {cracky = 3}, + drop = "default:permafrost", + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_grass_footstep", gain = 0.25}, + }), +}) + +minetest.register_node("default:sand", { + description = "Sand", + tiles = {"default_sand.png"}, + groups = {crumbly = 3, falling_node = 1, sand = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +minetest.register_node("default:desert_sand", { + description = "Desert Sand", + tiles = {"default_desert_sand.png"}, + groups = {crumbly = 3, falling_node = 1, sand = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +minetest.register_node("default:silver_sand", { + description = "Silver Sand", + tiles = {"default_silver_sand.png"}, + groups = {crumbly = 3, falling_node = 1, sand = 1}, + sounds = default.node_sound_sand_defaults(), +}) + + +minetest.register_node("default:gravel", { + description = "Gravel", + tiles = {"default_gravel.png"}, + groups = {crumbly = 2, falling_node = 1}, + sounds = default.node_sound_gravel_defaults(), + drop = { + max_items = 1, + items = { + {items = {'default:flint'}, rarity = 16}, + {items = {'default:gravel'}} + } + } +}) + +minetest.register_node("default:clay", { + description = "Clay", + tiles = {"default_clay.png"}, + groups = {crumbly = 3}, + drop = 'default:clay_lump 4', + sounds = default.node_sound_dirt_defaults(), +}) + + +minetest.register_node("default:snow", { + description = "Snow", + tiles = {"default_snow.png"}, + inventory_image = "default_snowball.png", + wield_image = "default_snowball.png", + paramtype = "light", + buildable_to = true, + floodable = true, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5}, + }, + }, + collision_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, -7 / 16, 0.5}, + }, + }, + groups = {crumbly = 3, falling_node = 1, puts_out_fire = 1, snowy = 1}, + sounds = default.node_sound_snow_defaults(), + + on_construct = function(pos) + pos.y = pos.y - 1 + if minetest.get_node(pos).name == "default:dirt_with_grass" then + minetest.set_node(pos, {name = "default:dirt_with_snow"}) + end + end, +}) + +minetest.register_node("default:snowblock", { + description = "Snow Block", + tiles = {"default_snow.png"}, + groups = {crumbly = 3, puts_out_fire = 1, cools_lava = 1, snowy = 1}, + sounds = default.node_sound_snow_defaults(), + + on_construct = function(pos) + pos.y = pos.y - 1 + if minetest.get_node(pos).name == "default:dirt_with_grass" then + minetest.set_node(pos, {name = "default:dirt_with_snow"}) + end + end, +}) + +-- 'is ground content = false' to avoid tunnels in sea ice or ice rivers +minetest.register_node("default:ice", { + description = "Ice", + tiles = {"default_ice.png"}, + is_ground_content = false, + paramtype = "light", + groups = {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 3}, + sounds = default.node_sound_glass_defaults(), +}) + +-- Mapgen-placed ice with 'is ground content = true' to contain tunnels +minetest.register_node("default:cave_ice", { + description = "Cave Ice", + tiles = {"default_ice.png"}, + paramtype = "light", + groups = {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 3, + not_in_creative_inventory = 1}, + drop = "default:ice", + sounds = default.node_sound_glass_defaults(), +}) + +-- +-- Trees +-- + +minetest.register_node("default:tree", { + description = "Apple Tree", + tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +minetest.register_node("default:wood", { + description = "Apple Wood Planks", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_wood.png"}, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:sapling", { + description = "Apple Tree Sapling", + drawtype = "plantlike", + tiles = {"default_sapling.png"}, + inventory_image = "default_sapling.png", + wield_image = "default_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, 7 / 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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -3, y = 1, z = -3}, + {x = 3, y = 6, z = 3}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + +minetest.register_node("default:leaves", { + description = "Apple Tree Leaves", + drawtype = "allfaces_optional", + waving = 1, + tiles = {"default_leaves.png"}, + special_tiles = {"default_leaves_simple.png"}, + paramtype = "light", + is_ground_content = false, + groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + { + -- player will get sapling with 1/20 chance + items = {'default:sapling'}, + rarity = 20, + }, + { + -- player will get leaves only if he get no saplings, + -- this is because max_items is 1 + items = {'default:leaves'}, + } + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:apple", { + description = "Apple", + drawtype = "plantlike", + tiles = {"default_apple.png"}, + inventory_image = "default_apple.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + is_ground_content = false, + selection_box = { + type = "fixed", + fixed = {-3 / 16, -7 / 16, -3 / 16, 3 / 16, 4 / 16, 3 / 16} + }, + groups = {fleshy = 3, dig_immediate = 3, flammable = 2, + leafdecay = 3, leafdecay_drop = 1, food_apple = 1}, + on_use = minetest.item_eat(2), + sounds = default.node_sound_leaves_defaults(), + + after_place_node = function(pos, placer, itemstack) + minetest.set_node(pos, {name = "default:apple", param2 = 1}) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if oldnode.param2 == 0 then + minetest.set_node(pos, {name = "default:apple_mark"}) + minetest.get_node_timer(pos):start(math.random(300, 1500)) + end + end, +}) + +minetest.register_node("default:apple_mark", { + description = "Apple Marker", + drawtype = "airlike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + drop = "", + groups = {not_in_creative_inventory = 1}, + on_timer = function(pos, elapsed) + if not minetest.find_node_near(pos, 1, "default:leaves") then + minetest.remove_node(pos) + elseif minetest.get_node_light(pos) < 11 then + minetest.get_node_timer(pos):start(200) + else + minetest.set_node(pos, {name = "default:apple"}) + end + end +}) + + +minetest.register_node("default:jungletree", { + description = "Jungle Tree", + tiles = {"default_jungletree_top.png", "default_jungletree_top.png", + "default_jungletree.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +minetest.register_node("default:junglewood", { + description = "Jungle Wood Planks", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_junglewood.png"}, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:jungleleaves", { + description = "Jungle Tree Leaves", + drawtype = "allfaces_optional", + waving = 1, + tiles = {"default_jungleleaves.png"}, + special_tiles = {"default_jungleleaves_simple.png"}, + paramtype = "light", + is_ground_content = false, + groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {'default:junglesapling'}, rarity = 20}, + {items = {'default:jungleleaves'}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:junglesapling", { + description = "Jungle Tree Sapling", + drawtype = "plantlike", + tiles = {"default_junglesapling.png"}, + inventory_image = "default_junglesapling.png", + wield_image = "default_junglesapling.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, 7 / 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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:junglesapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 15, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + +minetest.register_node("default:emergent_jungle_sapling", { + description = "Emergent Jungle Tree Sapling", + drawtype = "plantlike", + tiles = {"default_emergent_jungle_sapling.png"}, + inventory_image = "default_emergent_jungle_sapling.png", + wield_image = "default_emergent_jungle_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, 7 / 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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:emergent_jungle_sapling", + -- minp, maxp to be checked, relative to sapling pos + {x = -3, y = -5, z = -3}, + {x = 3, y = 31, z = 3}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + + +minetest.register_node("default:pine_tree", { + description = "Pine Tree", + tiles = {"default_pine_tree_top.png", "default_pine_tree_top.png", + "default_pine_tree.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 3, oddly_breakable_by_hand = 1, flammable = 3}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +minetest.register_node("default:pine_wood", { + description = "Pine Wood Planks", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_pine_wood.png"}, + is_ground_content = false, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:pine_needles",{ + description = "Pine Needles", + drawtype = "allfaces_optional", + tiles = {"default_pine_needles.png"}, + waving = 1, + paramtype = "light", + is_ground_content = false, + groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:pine_sapling"}, rarity = 20}, + {items = {"default:pine_needles"}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:pine_sapling", { + description = "Pine Tree Sapling", + drawtype = "plantlike", + tiles = {"default_pine_sapling.png"}, + inventory_image = "default_pine_sapling.png", + wield_image = "default_pine_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, 7 / 16, 4 / 16} + }, + groups = {snappy = 2, dig_immediate = 3, flammable = 3, + attached_node = 1, sapling = 1}, + sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:pine_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 14, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + + +minetest.register_node("default:acacia_tree", { + description = "Acacia Tree", + tiles = {"default_acacia_tree_top.png", "default_acacia_tree_top.png", + "default_acacia_tree.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +minetest.register_node("default:acacia_wood", { + description = "Acacia Wood Planks", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_acacia_wood.png"}, + is_ground_content = false, + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:acacia_leaves", { + description = "Acacia Tree Leaves", + drawtype = "allfaces_optional", + tiles = {"default_acacia_leaves.png"}, + special_tiles = {"default_acacia_leaves_simple.png"}, + waving = 1, + paramtype = "light", + is_ground_content = false, + groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:acacia_sapling"}, rarity = 20}, + {items = {"default:acacia_leaves"}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:acacia_sapling", { + description = "Acacia Tree Sapling", + drawtype = "plantlike", + tiles = {"default_acacia_sapling.png"}, + inventory_image = "default_acacia_sapling.png", + wield_image = "default_acacia_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, 7 / 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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:acacia_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -4, y = 1, z = -4}, + {x = 4, y = 7, z = 4}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + +minetest.register_node("default:aspen_tree", { + description = "Aspen Tree", + tiles = {"default_aspen_tree_top.png", "default_aspen_tree_top.png", + "default_aspen_tree.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {tree = 1, choppy = 3, oddly_breakable_by_hand = 1, flammable = 3}, + sounds = default.node_sound_wood_defaults(), + + on_place = minetest.rotate_node +}) + +minetest.register_node("default:aspen_wood", { + description = "Aspen Wood Planks", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_aspen_wood.png"}, + is_ground_content = false, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3, wood = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:aspen_leaves", { + description = "Aspen Tree Leaves", + drawtype = "allfaces_optional", + tiles = {"default_aspen_leaves.png"}, + waving = 1, + paramtype = "light", + is_ground_content = false, + groups = {snappy = 3, leafdecay = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:aspen_sapling"}, rarity = 20}, + {items = {"default:aspen_leaves"}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:aspen_sapling", { + description = "Aspen Tree Sapling", + drawtype = "plantlike", + tiles = {"default_aspen_sapling.png"}, + inventory_image = "default_aspen_sapling.png", + wield_image = "default_aspen_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, 0.5, 3 / 16} + }, + groups = {snappy = 2, dig_immediate = 3, flammable = 3, + attached_node = 1, sapling = 1}, + sounds = default.node_sound_leaves_defaults(), + + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:aspen_sapling", + -- minp, maxp to be checked, relative to sapling pos + -- minp_relative.y = 1 because sapling pos has been checked + {x = -2, y = 1, z = -2}, + {x = 2, y = 12, z = 2}, + -- maximum interval of interior volume check + 4) + + return itemstack + end, +}) + +-- +-- Ores +-- + +minetest.register_node("default:stone_with_coal", { + description = "Coal Ore", + tiles = {"default_stone.png^default_mineral_coal.png"}, + groups = {cracky = 3}, + drop = 'default:coal_lump', + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:coalblock", { + description = "Coal Block", + tiles = {"default_coal_block.png"}, + is_ground_content = false, + groups = {cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("default:stone_with_iron", { + description = "Iron Ore", + tiles = {"default_stone.png^default_mineral_iron.png"}, + groups = {cracky = 2}, + drop = 'default:iron_lump', + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:steelblock", { + description = "Steel Block", + tiles = {"default_steel_block.png"}, + is_ground_content = false, + groups = {cracky = 1, level = 2}, + sounds = default.node_sound_metal_defaults(), +}) + + +minetest.register_node("default:stone_with_copper", { + description = "Copper Ore", + tiles = {"default_stone.png^default_mineral_copper.png"}, + groups = {cracky = 2}, + drop = 'default:copper_lump', + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:copperblock", { + description = "Copper Block", + tiles = {"default_copper_block.png"}, + is_ground_content = false, + groups = {cracky = 1, level = 2}, + 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"}, + is_ground_content = false, + groups = {cracky = 1, level = 2}, + sounds = default.node_sound_metal_defaults(), +}) + + +minetest.register_node("default:stone_with_mese", { + description = "Mese Ore", + tiles = {"default_stone.png^default_mineral_mese.png"}, + groups = {cracky = 1}, + drop = "default:mese_crystal", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:mese", { + description = "Mese Block", + tiles = {"default_mese_block.png"}, + paramtype = "light", + groups = {cracky = 1, level = 2}, + sounds = default.node_sound_stone_defaults(), + light_source = 3, +}) + + +minetest.register_node("default:stone_with_gold", { + description = "Gold Ore", + tiles = {"default_stone.png^default_mineral_gold.png"}, + groups = {cracky = 2}, + drop = "default:gold_lump", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:goldblock", { + description = "Gold Block", + tiles = {"default_gold_block.png"}, + is_ground_content = false, + groups = {cracky = 1}, + sounds = default.node_sound_metal_defaults(), +}) + + +minetest.register_node("default:stone_with_diamond", { + description = "Diamond Ore", + tiles = {"default_stone.png^default_mineral_diamond.png"}, + groups = {cracky = 1}, + drop = "default:diamond", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:diamondblock", { + description = "Diamond Block", + tiles = {"default_diamond_block.png"}, + is_ground_content = false, + groups = {cracky = 1, level = 3}, + sounds = default.node_sound_stone_defaults(), +}) + +-- +-- Plantlife (non-cubic) +-- + +minetest.register_node("default:cactus", { + description = "Cactus", + tiles = {"default_cactus_top.png", "default_cactus_top.png", + "default_cactus_side.png"}, + paramtype2 = "facedir", + groups = {choppy = 3}, + sounds = default.node_sound_wood_defaults(), + on_place = minetest.rotate_node, +}) + +minetest.register_node("default:papyrus", { + description = "Papyrus", + drawtype = "plantlike", + tiles = {"default_papyrus.png"}, + inventory_image = "default_papyrus.png", + wield_image = "default_papyrus.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, 0.5, 6 / 16}, + }, + groups = {snappy = 3, flammable = 2}, + sounds = default.node_sound_leaves_defaults(), + + after_dig_node = function(pos, node, metadata, digger) + default.dig_up(pos, node, digger) + end, +}) + +minetest.register_node("default:dry_shrub", { + description = "Dry Shrub", + drawtype = "plantlike", + waving = 1, + tiles = {"default_dry_shrub.png"}, + inventory_image = "default_dry_shrub.png", + wield_image = "default_dry_shrub.png", + paramtype = "light", + paramtype2 = "meshoptions", + place_param2 = 4, + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, attached_node = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, 4 / 16, 6 / 16}, + }, +}) + +minetest.register_node("default:junglegrass", { + description = "Jungle Grass", + drawtype = "plantlike", + waving = 1, + visual_scale = 1.69, + tiles = {"default_junglegrass.png"}, + inventory_image = "default_junglegrass.png", + wield_image = "default_junglegrass.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flora = 1, attached_node = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, 0.5, 6 / 16}, + }, +}) + + +minetest.register_node("default:grass_1", { + description = "Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_grass_1.png"}, + -- Use texture of a taller grass stage in inventory + inventory_image = "default_grass_3.png", + wield_image = "default_grass_3.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flora = 1, attached_node = 1, grass = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -5 / 16, 6 / 16}, + }, + + on_place = function(itemstack, placer, pointed_thing) + -- place a random grass node + local stack = ItemStack("default:grass_" .. math.random(1,5)) + local ret = minetest.item_place(stack, placer, pointed_thing) + return ItemStack("default:grass_1 " .. + itemstack:get_count() - (1 - ret:get_count())) + end, +}) + +for i = 2, 5 do + minetest.register_node("default:grass_" .. i, { + description = "Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_grass_" .. i .. ".png"}, + inventory_image = "default_grass_" .. i .. ".png", + wield_image = "default_grass_" .. i .. ".png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + drop = "default:grass_1", + groups = {snappy = 3, flora = 1, attached_node = 1, + not_in_creative_inventory = 1, grass = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -3 / 16, 6 / 16}, + }, + }) +end + + +minetest.register_node("default:dry_grass_1", { + description = "Dry Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_dry_grass_1.png"}, + inventory_image = "default_dry_grass_3.png", + wield_image = "default_dry_grass_3.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, flora = 1, + attached_node = 1, dry_grass = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -3 / 16, 6 / 16}, + }, + + on_place = function(itemstack, placer, pointed_thing) + -- place a random dry grass node + local stack = ItemStack("default:dry_grass_" .. math.random(1, 5)) + local ret = minetest.item_place(stack, placer, pointed_thing) + return ItemStack("default:dry_grass_1 " .. + itemstack:get_count() - (1 - ret:get_count())) + end, +}) + +for i = 2, 5 do + minetest.register_node("default:dry_grass_" .. i, { + description = "Dry Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_dry_grass_" .. i .. ".png"}, + inventory_image = "default_dry_grass_" .. i .. ".png", + wield_image = "default_dry_grass_" .. i .. ".png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1, + not_in_creative_inventory=1, dry_grass = 1}, + drop = "default:dry_grass_1", + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -1 / 16, 6 / 16}, + }, + }) +end + + +minetest.register_node("default:fern_1", { + description = "Fern", + drawtype = "plantlike", + waving = 1, + tiles = {"default_fern_1.png"}, + inventory_image = "default_fern_1.png", + wield_image = "default_fern_1.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -0.25, 6 / 16}, + }, + + on_place = function(itemstack, placer, pointed_thing) + -- place a random fern node + local stack = ItemStack("default:fern_" .. math.random(1, 3)) + local ret = minetest.item_place(stack, placer, pointed_thing) + return ItemStack("default:fern_1 " .. + itemstack:get_count() - (1 - ret:get_count())) + end, +}) + +for i = 2, 3 do + minetest.register_node("default:fern_" .. i, { + description = "Fern", + drawtype = "plantlike", + waving = 1, + visual_scale = 2, + tiles = {"default_fern_" .. i .. ".png"}, + inventory_image = "default_fern_" .. i .. ".png", + wield_image = "default_fern_" .. i .. ".png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, flora = 1, attached_node = 1, + not_in_creative_inventory=1}, + drop = "default:fern_1", + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -0.25, 6 / 16}, + }, + }) +end + + +minetest.register_node("default:marram_grass_1", { + description = "Marram Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_marram_grass_1.png"}, + inventory_image = "default_marram_grass_1.png", + wield_image = "default_marram_grass_1.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, attached_node = 1}, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -0.25, 6 / 16}, + }, + + on_place = function(itemstack, placer, pointed_thing) + -- place a random marram grass node + local stack = ItemStack("default:marram_grass_" .. math.random(1, 3)) + local ret = minetest.item_place(stack, placer, pointed_thing) + return ItemStack("default:marram_grass_1 " .. + itemstack:get_count() - (1 - ret:get_count())) + end, +}) + +for i = 2, 3 do + minetest.register_node("default:marram_grass_" .. i, { + description = "Marram Grass", + drawtype = "plantlike", + waving = 1, + tiles = {"default_marram_grass_" .. i .. ".png"}, + inventory_image = "default_marram_grass_" .. i .. ".png", + wield_image = "default_marram_grass_" .. i .. ".png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, flammable = 3, attached_node = 1, + not_in_creative_inventory=1}, + drop = "default:marram_grass_1", + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = {-6 / 16, -0.5, -6 / 16, 6 / 16, -0.25, 6 / 16}, + }, + }) +end + + +minetest.register_node("default:bush_stem", { + description = "Bush Stem", + drawtype = "plantlike", + visual_scale = 1.41, + tiles = {"default_bush_stem.png"}, + inventory_image = "default_bush_stem.png", + wield_image = "default_bush_stem.png", + paramtype = "light", + sunlight_propagates = true, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + selection_box = { + type = "fixed", + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.5, 7 / 16}, + }, +}) + +minetest.register_node("default:bush_leaves", { + description = "Bush Leaves", + drawtype = "allfaces_optional", + waving = 1, + 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(300, 1500)) + 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:blueberry_bush_leaves_with_berries", { + description = "Blueberry Bush Leaves with Berries", + drawtype = "allfaces_optional", + waving = 1, + tiles = {"default_blueberry_bush_leaves.png^default_blueberry_overlay.png"}, + paramtype = "light", + groups = {snappy = 3, flammable = 2, leaves = 1, dig_immediate = 3}, + drop = "default:blueberries", + sounds = default.node_sound_leaves_defaults(), + node_dig_prediction = "default:blueberry_bush_leaves", + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + minetest.set_node(pos, {name = "default:blueberry_bush_leaves"}) + minetest.get_node_timer(pos):start(math.random(300, 1500)) + end, +}) + +minetest.register_node("default:blueberry_bush_leaves", { + description = "Blueberry Bush Leaves", + drawtype = "allfaces_optional", + waving = 1, + tiles = {"default_blueberry_bush_leaves.png"}, + paramtype = "light", + groups = {snappy = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:blueberry_bush_sapling"}, rarity = 5}, + {items = {"default:blueberry_bush_leaves"}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + on_timer = function(pos, elapsed) + if minetest.get_node_light(pos) < 11 then + minetest.get_node_timer(pos):start(200) + else + minetest.set_node(pos, {name = "default:blueberry_bush_leaves_with_berries"}) + end + end, + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:blueberry_bush_sapling", { + description = "Blueberry Bush Sapling", + drawtype = "plantlike", + tiles = {"default_blueberry_bush_sapling.png"}, + inventory_image = "default_blueberry_bush_sapling.png", + wield_image = "default_blueberry_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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:blueberry_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.41, + tiles = {"default_acacia_bush_stem.png"}, + inventory_image = "default_acacia_bush_stem.png", + wield_image = "default_acacia_bush_stem.png", + paramtype = "light", + sunlight_propagates = true, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + selection_box = { + type = "fixed", + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.5, 7 / 16}, + }, +}) + +minetest.register_node("default:acacia_bush_leaves", { + description = "Acacia Bush Leaves", + drawtype = "allfaces_optional", + waving = 1, + 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(300, 1500)) + 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, +}) + +minetest.register_node("default:pine_bush_stem", { + description = "Pine Bush Stem", + drawtype = "plantlike", + visual_scale = 1.41, + tiles = {"default_pine_bush_stem.png"}, + inventory_image = "default_pine_bush_stem.png", + wield_image = "default_pine_bush_stem.png", + paramtype = "light", + sunlight_propagates = true, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), + selection_box = { + type = "fixed", + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, 0.5, 7 / 16}, + }, +}) + +minetest.register_node("default:pine_bush_needles", { + description = "Pine Bush Needles", + drawtype = "allfaces_optional", + waving = 1, + tiles = {"default_pine_needles.png"}, + paramtype = "light", + groups = {snappy = 3, flammable = 2, leaves = 1}, + drop = { + max_items = 1, + items = { + {items = {"default:pine_bush_sapling"}, rarity = 5}, + {items = {"default:pine_bush_needles"}} + } + }, + sounds = default.node_sound_leaves_defaults(), + + after_place_node = default.after_place_leaves, +}) + +minetest.register_node("default:pine_bush_sapling", { + description = "Pine Bush Sapling", + drawtype = "plantlike", + tiles = {"default_pine_bush_sapling.png"}, + inventory_image = "default_pine_bush_sapling.png", + wield_image = "default_pine_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(300, 1500)) + end, + + on_place = function(itemstack, placer, pointed_thing) + itemstack = default.sapling_on_place(itemstack, placer, pointed_thing, + "default:pine_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:sand_with_kelp", { + description = "Kelp", + drawtype = "plantlike_rooted", + waving = 1, + tiles = {"default_sand.png"}, + special_tiles = {{name = "default_kelp.png", tileable_vertical = true}}, + inventory_image = "default_kelp.png", + paramtype = "light", + paramtype2 = "leveled", + groups = {snappy = 3}, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-2/16, 0.5, -2/16, 2/16, 3.5, 2/16}, + }, + }, + node_dig_prediction = "default:sand", + node_placement_prediction = "", + + on_place = function(itemstack, placer, pointed_thing) + -- Call on_rightclick if the pointed node defines it + if pointed_thing.type == "node" and placer and + not placer:get_player_control().sneak then + local node_ptu = minetest.get_node(pointed_thing.under) + local def_ptu = minetest.registered_nodes[node_ptu.name] + if def_ptu and def_ptu.on_rightclick then + return def_ptu.on_rightclick(pointed_thing.under, node_ptu, placer, + itemstack, pointed_thing) + end + end + + local pos = pointed_thing.under + if minetest.get_node(pos).name ~= "default:sand" then + return itemstack + end + + local height = math.random(4, 6) + local pos_top = {x = pos.x, y = pos.y + height, z = pos.z} + local node_top = minetest.get_node(pos_top) + local def_top = minetest.registered_nodes[node_top.name] + local player_name = placer:get_player_name() + + if def_top and def_top.liquidtype == "source" and + minetest.get_item_group(node_top.name, "water") > 0 then + if not minetest.is_protected(pos, player_name) and + not minetest.is_protected(pos_top, player_name) then + minetest.set_node(pos, {name = "default:sand_with_kelp", + param2 = height * 16}) + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + else + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos, player_name) + end + end + + return itemstack + end, + + after_destruct = function(pos, oldnode) + minetest.set_node(pos, {name = "default:sand"}) + end +}) + + +-- +-- Corals +-- + +minetest.register_node("default:coral_green", { + description = "Green Coral", + drawtype = "plantlike_rooted", + waving = 1, + paramtype = "light", + tiles = {"default_coral_skeleton.png"}, + special_tiles = {{name = "default_coral_green.png", tileable_vertical = true}}, + inventory_image = "default_coral_green.png", + groups = {snappy = 3}, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-4/16, 0.5, -4/16, 4/16, 1.5, 4/16}, + }, + }, + node_dig_prediction = "default:coral_skeleton", + node_placement_prediction = "", + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" or not placer then + return itemstack + end + + local player_name = placer:get_player_name() + local pos_under = pointed_thing.under + local pos_above = pointed_thing.above + + if minetest.get_node(pos_under).name ~= "default:coral_skeleton" or + minetest.get_node(pos_above).name ~= "default:water_source" then + return itemstack + end + + if minetest.is_protected(pos_under, player_name) or + minetest.is_protected(pos_above, player_name) then + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos_under, player_name) + return itemstack + end + + minetest.set_node(pos_under, {name = "default:coral_green"}) + if not (creative and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + + return itemstack + end, + after_destruct = function(pos, oldnode) + minetest.set_node(pos, {name = "default:coral_skeleton"}) + end, +}) + +minetest.register_node("default:coral_pink", { + description = "Pink Coral", + drawtype = "plantlike_rooted", + waving = 1, + paramtype = "light", + tiles = {"default_coral_skeleton.png"}, + special_tiles = {{name = "default_coral_pink.png", tileable_vertical = true}}, + inventory_image = "default_coral_pink.png", + groups = {snappy = 3}, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-4/16, 0.5, -4/16, 4/16, 1.5, 4/16}, + }, + }, + node_dig_prediction = "default:coral_skeleton", + node_placement_prediction = "", + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" or not placer then + return itemstack + end + + local player_name = placer:get_player_name() + local pos_under = pointed_thing.under + local pos_above = pointed_thing.above + + if minetest.get_node(pos_under).name ~= "default:coral_skeleton" or + minetest.get_node(pos_above).name ~= "default:water_source" then + return itemstack + end + + if minetest.is_protected(pos_under, player_name) or + minetest.is_protected(pos_above, player_name) then + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos_under, player_name) + return itemstack + end + + minetest.set_node(pos_under, {name = "default:coral_pink"}) + if not (creative and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + + return itemstack + end, + after_destruct = function(pos, oldnode) + minetest.set_node(pos, {name = "default:coral_skeleton"}) + end, +}) + +minetest.register_node("default:coral_cyan", { + description = "Cyan Coral", + drawtype = "plantlike_rooted", + waving = 1, + paramtype = "light", + tiles = {"default_coral_skeleton.png"}, + special_tiles = {{name = "default_coral_cyan.png", tileable_vertical = true}}, + inventory_image = "default_coral_cyan.png", + groups = {snappy = 3}, + selection_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-4/16, 0.5, -4/16, 4/16, 1.5, 4/16}, + }, + }, + node_dig_prediction = "default:coral_skeleton", + node_placement_prediction = "", + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" or not placer then + return itemstack + end + + local player_name = placer:get_player_name() + local pos_under = pointed_thing.under + local pos_above = pointed_thing.above + + if minetest.get_node(pos_under).name ~= "default:coral_skeleton" or + minetest.get_node(pos_above).name ~= "default:water_source" then + return itemstack + end + + if minetest.is_protected(pos_under, player_name) or + minetest.is_protected(pos_above, player_name) then + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos_under, player_name) + return itemstack + end + + minetest.set_node(pos_under, {name = "default:coral_cyan"}) + if not (creative and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + + return itemstack + end, + after_destruct = function(pos, oldnode) + minetest.set_node(pos, {name = "default:coral_skeleton"}) + end, +}) + +minetest.register_node("default:coral_brown", { + description = "Brown Coral", + tiles = {"default_coral_brown.png"}, + groups = {cracky = 3}, + drop = "default:coral_skeleton", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:coral_orange", { + description = "Orange Coral", + tiles = {"default_coral_orange.png"}, + groups = {cracky = 3}, + drop = "default:coral_skeleton", + sounds = default.node_sound_stone_defaults(), +}) + +minetest.register_node("default:coral_skeleton", { + description = "Coral Skeleton", + tiles = {"default_coral_skeleton.png"}, + groups = {cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + + +-- +-- Liquids +-- + +minetest.register_node("default:water_source", { + description = "Water Source", + drawtype = "liquid", + tiles = { + { + name = "default_water_source_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + { + name = "default_water_source_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + alpha = 160, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "default:water_flowing", + liquid_alternative_source = "default:water_source", + liquid_viscosity = 1, + post_effect_color = {a = 103, r = 30, g = 60, b = 90}, + groups = {water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("default:water_flowing", { + description = "Flowing Water", + drawtype = "flowingliquid", + tiles = {"default_water.png"}, + special_tiles = { + { + name = "default_water_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + { + name = "default_water_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + }, + alpha = 160, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "default:water_flowing", + liquid_alternative_source = "default:water_source", + liquid_viscosity = 1, + post_effect_color = {a = 103, r = 30, g = 60, b = 90}, + groups = {water = 3, liquid = 3, puts_out_fire = 1, + not_in_creative_inventory = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) + + +minetest.register_node("default:river_water_source", { + description = "River Water Source", + drawtype = "liquid", + tiles = { + { + name = "default_river_water_source_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + { + name = "default_river_water_source_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + alpha = 160, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "default:river_water_flowing", + liquid_alternative_source = "default:river_water_source", + liquid_viscosity = 1, + -- Not renewable to avoid horizontal spread of water sources in sloping + -- rivers that can cause water to overflow riverbanks and cause floods. + -- River water source is instead made renewable by the 'force renew' + -- option used in the 'bucket' mod by the river water bucket. + liquid_renewable = false, + liquid_range = 2, + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + groups = {water = 3, liquid = 3, puts_out_fire = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) + +minetest.register_node("default:river_water_flowing", { + description = "Flowing River Water", + drawtype = "flowingliquid", + tiles = {"default_river_water.png"}, + special_tiles = { + { + name = "default_river_water_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + { + name = "default_river_water_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.8, + }, + }, + }, + alpha = 160, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "default:river_water_flowing", + liquid_alternative_source = "default:river_water_source", + liquid_viscosity = 1, + liquid_renewable = false, + liquid_range = 2, + post_effect_color = {a = 103, r = 30, g = 76, b = 90}, + groups = {water = 3, liquid = 3, puts_out_fire = 1, + not_in_creative_inventory = 1, cools_lava = 1}, + sounds = default.node_sound_water_defaults(), +}) + + +minetest.register_node("default:lava_source", { + description = "Lava Source", + drawtype = "liquid", + tiles = { + { + name = "default_lava_source_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0, + }, + }, + { + name = "default_lava_source_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0, + }, + }, + }, + paramtype = "light", + light_source = default.LIGHT_MAX - 1, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "source", + liquid_alternative_flowing = "default:lava_flowing", + liquid_alternative_source = "default:lava_source", + liquid_viscosity = 7, + liquid_renewable = false, + damage_per_second = 4 * 2, + post_effect_color = {a = 191, r = 255, g = 64, b = 0}, + groups = {lava = 3, liquid = 2, igniter = 1}, +}) + +minetest.register_node("default:lava_flowing", { + description = "Flowing Lava", + drawtype = "flowingliquid", + tiles = {"default_lava.png"}, + special_tiles = { + { + name = "default_lava_flowing_animated.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.3, + }, + }, + { + name = "default_lava_flowing_animated.png", + backface_culling = true, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.3, + }, + }, + }, + paramtype = "light", + paramtype2 = "flowingliquid", + light_source = default.LIGHT_MAX - 1, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + liquidtype = "flowing", + liquid_alternative_flowing = "default:lava_flowing", + liquid_alternative_source = "default:lava_source", + liquid_viscosity = 7, + liquid_renewable = false, + damage_per_second = 4 * 2, + post_effect_color = {a = 191, r = 255, g = 64, b = 0}, + groups = {lava = 3, liquid = 2, igniter = 1, + not_in_creative_inventory = 1}, +}) + +-- +-- Tools / "Advanced" crafting / Non-"natural" +-- + +local bookshelf_formspec = + "size[8,7;]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[context;books;0,0.3;8,2;]" .. + "list[current_player;main;0,2.85;8,1;]" .. + "list[current_player;main;0,4.08;8,3;8]" .. + "listring[context;books]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0,2.85) + +local function update_bookshelf(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local invlist = inv:get_list("books") + + local formspec = bookshelf_formspec + -- Inventory slots overlay + local bx, by = 0, 0.3 + local n_written, n_empty = 0, 0 + for i = 1, 16 do + if i == 9 then + bx = 0 + by = by + 1 + end + local stack = invlist[i] + if stack:is_empty() then + formspec = formspec .. + "image[" .. bx .. "," .. by .. ";1,1;default_bookshelf_slot.png]" + else + local metatable = stack:get_meta():to_table() or {} + if metatable.fields and metatable.fields.text then + n_written = n_written + stack:get_count() + else + n_empty = n_empty + stack:get_count() + end + end + bx = bx + 1 + end + meta:set_string("formspec", formspec) + if n_written + n_empty == 0 then + meta:set_string("infotext", "Empty Bookshelf") + else + meta:set_string("infotext", "Bookshelf (" .. n_written .. + " written, " .. n_empty .. " empty books)") + end +end + +minetest.register_node("default:bookshelf", { + description = "Bookshelf", + tiles = {"default_wood.png", "default_wood.png", "default_wood.png", + "default_wood.png", "default_bookshelf.png", "default_bookshelf.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults(), + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("books", 8 * 2) + update_bookshelf(pos) + end, + can_dig = function(pos,player) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("books") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack) + if minetest.get_item_group(stack:get_name(), "book") ~= 0 then + return stack:get_count() + end + return 0 + end, + 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 bookshelf at " .. minetest.pos_to_string(pos)) + update_bookshelf(pos) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.log("action", player:get_player_name() .. + " puts stuff to bookshelf at " .. minetest.pos_to_string(pos)) + update_bookshelf(pos) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + minetest.log("action", player:get_player_name() .. + " takes stuff from bookshelf at " .. minetest.pos_to_string(pos)) + update_bookshelf(pos) + end, + on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "books", drops) + drops[#drops+1] = "default:bookshelf" + minetest.remove_node(pos) + return drops + end, +}) + +local function register_sign(material, desc, def) + minetest.register_node("default:sign_wall_" .. material, { + description = desc .. " Sign", + drawtype = "nodebox", + tiles = {"default_sign_wall_" .. material .. ".png"}, + inventory_image = "default_sign_" .. material .. ".png", + wield_image = "default_sign_" .. material .. ".png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + is_ground_content = false, + walkable = false, + node_box = { + type = "wallmounted", + wall_top = {-0.4375, 0.4375, -0.3125, 0.4375, 0.5, 0.3125}, + wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}, + wall_side = {-0.5, -0.3125, -0.4375, -0.4375, 0.3125, 0.4375}, + }, + groups = def.groups, + legacy_wallmounted = true, + sounds = def.sounds, + + on_construct = function(pos) + --local n = minetest.get_node(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", "field[text;;${text}]") + end, + on_receive_fields = function(pos, formname, fields, sender) + --print("Sign at "..minetest.pos_to_string(pos).." got "..dump(fields)) + local player_name = sender:get_player_name() + if minetest.is_protected(pos, player_name) then + minetest.record_protection_violation(pos, player_name) + return + end + local meta = minetest.get_meta(pos) + if not fields.text then return end + minetest.log("action", (player_name or "") .. " wrote \"" .. + fields.text .. "\" to sign at " .. minetest.pos_to_string(pos)) + meta:set_string("text", fields.text) + meta:set_string("infotext", '"' .. fields.text .. '"') + end, + }) +end + +register_sign("wood", "Wooden", { + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 2, attached_node = 1, flammable = 2, oddly_breakable_by_hand = 3} +}) + +register_sign("steel", "Steel", { + sounds = default.node_sound_metal_defaults(), + groups = {cracky = 2, attached_node = 1} +}) + +minetest.register_node("default:ladder_wood", { + description = "Wooden Ladder", + drawtype = "signlike", + tiles = {"default_ladder_wood.png"}, + inventory_image = "default_ladder_wood.png", + wield_image = "default_ladder_wood.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + climbable = true, + is_ground_content = false, + selection_box = { + type = "wallmounted", + --wall_top = = + --wall_bottom = = + --wall_side = = + }, + groups = {choppy = 2, oddly_breakable_by_hand = 3, flammable = 2}, + legacy_wallmounted = true, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("default:ladder_steel", { + description = "Steel Ladder", + drawtype = "signlike", + tiles = {"default_ladder_steel.png"}, + inventory_image = "default_ladder_steel.png", + wield_image = "default_ladder_steel.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + climbable = true, + is_ground_content = false, + selection_box = { + type = "wallmounted", + --wall_top = = + --wall_bottom = = + --wall_side = = + }, + groups = {cracky = 2}, + sounds = default.node_sound_metal_defaults(), +}) + +default.register_fence("default:fence_wood", { + description = "Apple Wood Fence", + texture = "default_fence_wood.png", + inventory_image = "default_fence_overlay.png^default_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence("default:fence_acacia_wood", { + description = "Acacia Wood Fence", + texture = "default_fence_acacia_wood.png", + inventory_image = "default_fence_overlay.png^default_acacia_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_acacia_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + material = "default:acacia_wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence("default:fence_junglewood", { + 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", + material = "default:junglewood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence("default:fence_pine_wood", { + description = "Pine Wood Fence", + texture = "default_fence_pine_wood.png", + inventory_image = "default_fence_overlay.png^default_pine_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_pine_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + material = "default:pine_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence("default:fence_aspen_wood", { + description = "Aspen Wood Fence", + texture = "default_fence_aspen_wood.png", + inventory_image = "default_fence_overlay.png^default_aspen_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_overlay.png^default_aspen_wood.png^" .. + "default_fence_overlay.png^[makealpha:255,126,126", + material = "default:aspen_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence_rail("default:fence_rail_wood", { + description = "Apple Wood Fence Rail", + texture = "default_fence_rail_wood.png", + inventory_image = "default_fence_rail_overlay.png^default_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_rail_overlay.png^default_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence_rail("default:fence_rail_acacia_wood", { + description = "Acacia Wood Fence Rail", + texture = "default_fence_rail_acacia_wood.png", + inventory_image = "default_fence_rail_overlay.png^default_acacia_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_rail_overlay.png^default_acacia_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + material = "default:acacia_wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence_rail("default:fence_rail_junglewood", { + description = "Jungle Wood Fence Rail", + texture = "default_fence_rail_junglewood.png", + inventory_image = "default_fence_rail_overlay.png^default_junglewood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_rail_overlay.png^default_junglewood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + material = "default:junglewood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence_rail("default:fence_rail_pine_wood", { + description = "Pine Wood Fence Rail", + texture = "default_fence_rail_pine_wood.png", + inventory_image = "default_fence_rail_overlay.png^default_pine_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_rail_overlay.png^default_pine_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + material = "default:pine_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults() +}) + +default.register_fence_rail("default:fence_rail_aspen_wood", { + description = "Aspen Wood Fence Rail", + texture = "default_fence_rail_aspen_wood.png", + inventory_image = "default_fence_rail_overlay.png^default_aspen_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + wield_image = "default_fence_rail_overlay.png^default_aspen_wood.png^" .. + "default_fence_rail_overlay.png^[makealpha:255,126,126", + material = "default:aspen_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2}, + sounds = default.node_sound_wood_defaults() +}) +minetest.register_alias("default:glass", "default:glass_white") +for i = 1, #dye.dyes do + local c = dye.dyes[i][1] + if c == "dark_grey" then + c = "darkgrey" + elseif c == "dark_green" then + c = "darkgreen" + end + minetest.register_node("default:glass_" .. c, { + description = dye.dyes[i][2] .. " Glass", + drawtype = "glasslike_framed_optional", + tiles = {"default_glass.png^[colorize:" .. c, "default_glass_detail.png^[colorize:" .. c}, + paramtype = "light", + paramtype2 = "glasslikeliquidlevel", + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 3, glass = 1, oddly_breakable_by_hand = 3}, + sounds = default.node_sound_glass_defaults(), + }) + minetest.register_craft({ + type = "shapeless", + output = "default:glass_" .. c, + recipe = {"group:glass", "dye:" .. dye.dyes[i][1]}, + }) +end + +minetest.register_node("default:obsidian_glass", { + description = "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(), + groups = {cracky = 3}, +}) + + +minetest.register_node("default:brick", { + description = "Brick Block", + paramtype2 = "facedir", + place_param2 = 0, + tiles = {"default_brick.png"}, + is_ground_content = false, + groups = {cracky = 3}, + sounds = default.node_sound_stone_defaults(), +}) + + +minetest.register_node("default:meselamp", { + description = "Mese Lamp", + drawtype = "glasslike", + tiles = {"default_meselamp.png"}, + paramtype = "light", + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 3, oddly_breakable_by_hand = 3}, + sounds = default.node_sound_glass_defaults(), + 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 +-- + +minetest.register_node("default:cloud", { + description = "Cloud", + tiles = {"default_cloud.png"}, + is_ground_content = false, + 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, +}) + +default.register_leafdecay({ + trunks = {"default:pine_bush_stem"}, + leaves = {"default:pine_bush_needles"}, + radius = 1, +}) diff --git a/mods/default/schematics/acacia_bush.mts b/mods/default/schematics/acacia_bush.mts new file mode 100644 index 0000000..3322e3b Binary files /dev/null and b/mods/default/schematics/acacia_bush.mts differ diff --git a/mods/default/schematics/acacia_log.mts b/mods/default/schematics/acacia_log.mts new file mode 100644 index 0000000..aff3bd6 Binary files /dev/null and b/mods/default/schematics/acacia_log.mts differ diff --git a/mods/default/schematics/acacia_tree.mts b/mods/default/schematics/acacia_tree.mts new file mode 100644 index 0000000..9b23498 Binary files /dev/null and b/mods/default/schematics/acacia_tree.mts differ diff --git a/mods/default/schematics/acacia_tree_from_sapling.mts b/mods/default/schematics/acacia_tree_from_sapling.mts new file mode 100644 index 0000000..c32a995 Binary files /dev/null and b/mods/default/schematics/acacia_tree_from_sapling.mts differ diff --git a/mods/default/schematics/apple_log.mts b/mods/default/schematics/apple_log.mts new file mode 100644 index 0000000..92fb900 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 new file mode 100644 index 0000000..d56cd54 Binary files /dev/null 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 new file mode 100644 index 0000000..2325100 Binary files /dev/null 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 0000000..d0c723d 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 new file mode 100644 index 0000000..429a831 Binary files /dev/null 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 new file mode 100644 index 0000000..b7ab3ee Binary files /dev/null and b/mods/default/schematics/aspen_tree_from_sapling.mts differ diff --git a/mods/default/schematics/blueberry_bush.mts b/mods/default/schematics/blueberry_bush.mts new file mode 100644 index 0000000..cf4d8ef Binary files /dev/null and b/mods/default/schematics/blueberry_bush.mts differ diff --git a/mods/default/schematics/bush.mts b/mods/default/schematics/bush.mts new file mode 100644 index 0000000..d08cf5f Binary files /dev/null and b/mods/default/schematics/bush.mts differ diff --git a/mods/default/schematics/emergent_jungle_tree.mts b/mods/default/schematics/emergent_jungle_tree.mts new file mode 100644 index 0000000..b526430 Binary files /dev/null and b/mods/default/schematics/emergent_jungle_tree.mts differ diff --git a/mods/default/schematics/emergent_jungle_tree_from_sapling.mts b/mods/default/schematics/emergent_jungle_tree_from_sapling.mts new file mode 100644 index 0000000..cb4e4e9 Binary files /dev/null and b/mods/default/schematics/emergent_jungle_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 0000000..34dca43 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 new file mode 100644 index 0000000..fe93c8c Binary files /dev/null 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 new file mode 100644 index 0000000..f32d312 Binary files /dev/null and b/mods/default/schematics/jungle_tree_from_sapling.mts differ diff --git a/mods/default/schematics/large_cactus.mts b/mods/default/schematics/large_cactus.mts new file mode 100644 index 0000000..b71077b Binary files /dev/null and b/mods/default/schematics/large_cactus.mts differ diff --git a/mods/default/schematics/papyrus.mts b/mods/default/schematics/papyrus.mts new file mode 100644 index 0000000..1333a7c Binary files /dev/null and b/mods/default/schematics/papyrus.mts differ diff --git a/mods/default/schematics/pine_bush.mts b/mods/default/schematics/pine_bush.mts new file mode 100644 index 0000000..ca572a7 Binary files /dev/null and b/mods/default/schematics/pine_bush.mts differ diff --git a/mods/default/schematics/pine_log.mts b/mods/default/schematics/pine_log.mts new file mode 100644 index 0000000..d51a489 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 new file mode 100644 index 0000000..c80532a Binary files /dev/null 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 new file mode 100644 index 0000000..0800387 Binary files /dev/null and b/mods/default/schematics/pine_tree_from_sapling.mts differ diff --git a/mods/default/schematics/small_pine_tree.mts b/mods/default/schematics/small_pine_tree.mts new file mode 100644 index 0000000..1b27a84 Binary files /dev/null and b/mods/default/schematics/small_pine_tree.mts differ diff --git a/mods/default/schematics/small_pine_tree_from_sapling.mts b/mods/default/schematics/small_pine_tree_from_sapling.mts new file mode 100644 index 0000000..dc438a9 Binary files /dev/null and b/mods/default/schematics/small_pine_tree_from_sapling.mts differ diff --git a/mods/default/schematics/snowy_pine_tree_from_sapling.mts b/mods/default/schematics/snowy_pine_tree_from_sapling.mts new file mode 100644 index 0000000..3d502a3 Binary files /dev/null and b/mods/default/schematics/snowy_pine_tree_from_sapling.mts differ diff --git a/mods/default/schematics/snowy_small_pine_tree_from_sapling.mts b/mods/default/schematics/snowy_small_pine_tree_from_sapling.mts new file mode 100644 index 0000000..76fe345 Binary files /dev/null and b/mods/default/schematics/snowy_small_pine_tree_from_sapling.mts differ diff --git a/mods/default/sounds/default_break_glass.1.ogg b/mods/default/sounds/default_break_glass.1.ogg new file mode 100644 index 0000000..b1ccc5f Binary files /dev/null and b/mods/default/sounds/default_break_glass.1.ogg differ diff --git a/mods/default/sounds/default_break_glass.2.ogg b/mods/default/sounds/default_break_glass.2.ogg new file mode 100644 index 0000000..b6cc9e8 Binary files /dev/null and b/mods/default/sounds/default_break_glass.2.ogg differ diff --git a/mods/default/sounds/default_break_glass.3.ogg b/mods/default/sounds/default_break_glass.3.ogg new file mode 100644 index 0000000..ae6a6bf Binary files /dev/null and b/mods/default/sounds/default_break_glass.3.ogg differ diff --git a/mods/default/sounds/default_chest_close.ogg b/mods/default/sounds/default_chest_close.ogg new file mode 100644 index 0000000..068d900 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 0000000..40b0b93 Binary files /dev/null and b/mods/default/sounds/default_chest_open.ogg differ diff --git a/mods/default/sounds/default_cool_lava.1.ogg b/mods/default/sounds/default_cool_lava.1.ogg new file mode 100644 index 0000000..42506dd Binary files /dev/null and b/mods/default/sounds/default_cool_lava.1.ogg differ diff --git a/mods/default/sounds/default_cool_lava.2.ogg b/mods/default/sounds/default_cool_lava.2.ogg new file mode 100644 index 0000000..2747ab8 Binary files /dev/null and b/mods/default/sounds/default_cool_lava.2.ogg differ diff --git a/mods/default/sounds/default_cool_lava.3.ogg b/mods/default/sounds/default_cool_lava.3.ogg new file mode 100644 index 0000000..8baeac3 Binary files /dev/null and b/mods/default/sounds/default_cool_lava.3.ogg differ diff --git a/mods/default/sounds/default_dig_choppy.ogg b/mods/default/sounds/default_dig_choppy.ogg new file mode 100644 index 0000000..e2ecd84 Binary files /dev/null and b/mods/default/sounds/default_dig_choppy.ogg differ diff --git a/mods/default/sounds/default_dig_cracky.ogg b/mods/default/sounds/default_dig_cracky.ogg new file mode 100644 index 0000000..da11679 Binary files /dev/null and b/mods/default/sounds/default_dig_cracky.ogg differ diff --git a/mods/default/sounds/default_dig_crumbly.ogg b/mods/default/sounds/default_dig_crumbly.ogg new file mode 100644 index 0000000..a0b2a1f Binary files /dev/null and b/mods/default/sounds/default_dig_crumbly.ogg differ diff --git a/mods/default/sounds/default_dig_dig_immediate.ogg b/mods/default/sounds/default_dig_dig_immediate.ogg new file mode 100644 index 0000000..e65d766 Binary files /dev/null and b/mods/default/sounds/default_dig_dig_immediate.ogg differ diff --git a/mods/default/sounds/default_dig_metal.ogg b/mods/default/sounds/default_dig_metal.ogg new file mode 100644 index 0000000..0b58509 Binary files /dev/null and b/mods/default/sounds/default_dig_metal.ogg differ diff --git a/mods/default/sounds/default_dig_oddly_breakable_by_hand.ogg b/mods/default/sounds/default_dig_oddly_breakable_by_hand.ogg new file mode 100644 index 0000000..ef4d7b1 Binary files /dev/null and b/mods/default/sounds/default_dig_oddly_breakable_by_hand.ogg differ diff --git a/mods/default/sounds/default_dig_snappy.ogg b/mods/default/sounds/default_dig_snappy.ogg new file mode 100644 index 0000000..3686fcd Binary files /dev/null and b/mods/default/sounds/default_dig_snappy.ogg differ diff --git a/mods/default/sounds/default_dirt_footstep.1.ogg b/mods/default/sounds/default_dirt_footstep.1.ogg new file mode 100644 index 0000000..201aa3b Binary files /dev/null and b/mods/default/sounds/default_dirt_footstep.1.ogg differ diff --git a/mods/default/sounds/default_dirt_footstep.2.ogg b/mods/default/sounds/default_dirt_footstep.2.ogg new file mode 100644 index 0000000..2667dbc Binary files /dev/null and b/mods/default/sounds/default_dirt_footstep.2.ogg differ diff --git a/mods/default/sounds/default_dug_metal.1.ogg b/mods/default/sounds/default_dug_metal.1.ogg new file mode 100644 index 0000000..5d6cb5b Binary files /dev/null and b/mods/default/sounds/default_dug_metal.1.ogg differ diff --git a/mods/default/sounds/default_dug_metal.2.ogg b/mods/default/sounds/default_dug_metal.2.ogg new file mode 100644 index 0000000..63567fc Binary files /dev/null and b/mods/default/sounds/default_dug_metal.2.ogg differ diff --git a/mods/default/sounds/default_dug_node.1.ogg b/mods/default/sounds/default_dug_node.1.ogg new file mode 100644 index 0000000..c04975d Binary files /dev/null and b/mods/default/sounds/default_dug_node.1.ogg differ diff --git a/mods/default/sounds/default_dug_node.2.ogg b/mods/default/sounds/default_dug_node.2.ogg new file mode 100644 index 0000000..9f20926 Binary files /dev/null and b/mods/default/sounds/default_dug_node.2.ogg differ diff --git a/mods/default/sounds/default_glass_footstep.ogg b/mods/default/sounds/default_glass_footstep.ogg new file mode 100644 index 0000000..191287a Binary files /dev/null and b/mods/default/sounds/default_glass_footstep.ogg differ diff --git a/mods/default/sounds/default_grass_footstep.1.ogg b/mods/default/sounds/default_grass_footstep.1.ogg new file mode 100644 index 0000000..22d1ad6 Binary files /dev/null and b/mods/default/sounds/default_grass_footstep.1.ogg differ diff --git a/mods/default/sounds/default_grass_footstep.2.ogg b/mods/default/sounds/default_grass_footstep.2.ogg new file mode 100644 index 0000000..4ccd8a0 Binary files /dev/null and b/mods/default/sounds/default_grass_footstep.2.ogg differ diff --git a/mods/default/sounds/default_grass_footstep.3.ogg b/mods/default/sounds/default_grass_footstep.3.ogg new file mode 100644 index 0000000..20db84e Binary files /dev/null and b/mods/default/sounds/default_grass_footstep.3.ogg differ diff --git a/mods/default/sounds/default_gravel_footstep.1.ogg b/mods/default/sounds/default_gravel_footstep.1.ogg new file mode 100644 index 0000000..8d260ce Binary files /dev/null and b/mods/default/sounds/default_gravel_footstep.1.ogg differ diff --git a/mods/default/sounds/default_gravel_footstep.2.ogg b/mods/default/sounds/default_gravel_footstep.2.ogg new file mode 100644 index 0000000..2aba2c6 Binary files /dev/null and b/mods/default/sounds/default_gravel_footstep.2.ogg differ diff --git a/mods/default/sounds/default_gravel_footstep.3.ogg b/mods/default/sounds/default_gravel_footstep.3.ogg new file mode 100644 index 0000000..1bcd8a1 Binary files /dev/null and b/mods/default/sounds/default_gravel_footstep.3.ogg differ diff --git a/mods/default/sounds/default_gravel_footstep.4.ogg b/mods/default/sounds/default_gravel_footstep.4.ogg new file mode 100644 index 0000000..696c9ff Binary files /dev/null and b/mods/default/sounds/default_gravel_footstep.4.ogg differ diff --git a/mods/default/sounds/default_hard_footstep.1.ogg b/mods/default/sounds/default_hard_footstep.1.ogg new file mode 100644 index 0000000..1748bc5 Binary files /dev/null and b/mods/default/sounds/default_hard_footstep.1.ogg differ diff --git a/mods/default/sounds/default_hard_footstep.2.ogg b/mods/default/sounds/default_hard_footstep.2.ogg new file mode 100644 index 0000000..fe39fd7 Binary files /dev/null and b/mods/default/sounds/default_hard_footstep.2.ogg differ diff --git a/mods/default/sounds/default_hard_footstep.3.ogg b/mods/default/sounds/default_hard_footstep.3.ogg new file mode 100644 index 0000000..5030e06 Binary files /dev/null and b/mods/default/sounds/default_hard_footstep.3.ogg differ diff --git a/mods/default/sounds/default_item_smoke.ogg b/mods/default/sounds/default_item_smoke.ogg new file mode 100644 index 0000000..038a46e Binary files /dev/null and b/mods/default/sounds/default_item_smoke.ogg differ diff --git a/mods/default/sounds/default_metal_footstep.1.ogg b/mods/default/sounds/default_metal_footstep.1.ogg new file mode 100644 index 0000000..841286b Binary files /dev/null and b/mods/default/sounds/default_metal_footstep.1.ogg differ diff --git a/mods/default/sounds/default_metal_footstep.2.ogg b/mods/default/sounds/default_metal_footstep.2.ogg new file mode 100644 index 0000000..aa61ed3 Binary files /dev/null and b/mods/default/sounds/default_metal_footstep.2.ogg differ diff --git a/mods/default/sounds/default_metal_footstep.3.ogg b/mods/default/sounds/default_metal_footstep.3.ogg new file mode 100644 index 0000000..4cc1ca4 Binary files /dev/null and b/mods/default/sounds/default_metal_footstep.3.ogg differ diff --git a/mods/default/sounds/default_place_node.1.ogg b/mods/default/sounds/default_place_node.1.ogg new file mode 100644 index 0000000..46b9756 Binary files /dev/null and b/mods/default/sounds/default_place_node.1.ogg differ diff --git a/mods/default/sounds/default_place_node.2.ogg b/mods/default/sounds/default_place_node.2.ogg new file mode 100644 index 0000000..d34c01a Binary files /dev/null and b/mods/default/sounds/default_place_node.2.ogg differ diff --git a/mods/default/sounds/default_place_node.3.ogg b/mods/default/sounds/default_place_node.3.ogg new file mode 100644 index 0000000..fc29365 Binary files /dev/null and b/mods/default/sounds/default_place_node.3.ogg differ diff --git a/mods/default/sounds/default_place_node_hard.1.ogg b/mods/default/sounds/default_place_node_hard.1.ogg new file mode 100644 index 0000000..9f97fac Binary files /dev/null and b/mods/default/sounds/default_place_node_hard.1.ogg differ diff --git a/mods/default/sounds/default_place_node_hard.2.ogg b/mods/default/sounds/default_place_node_hard.2.ogg new file mode 100644 index 0000000..1d3b3de Binary files /dev/null and b/mods/default/sounds/default_place_node_hard.2.ogg differ diff --git a/mods/default/sounds/default_place_node_metal.1.ogg b/mods/default/sounds/default_place_node_metal.1.ogg new file mode 100644 index 0000000..5da085e Binary files /dev/null and b/mods/default/sounds/default_place_node_metal.1.ogg differ diff --git a/mods/default/sounds/default_place_node_metal.2.ogg b/mods/default/sounds/default_place_node_metal.2.ogg new file mode 100644 index 0000000..5ee67fc Binary files /dev/null and b/mods/default/sounds/default_place_node_metal.2.ogg differ diff --git a/mods/default/sounds/default_sand_footstep.1.ogg b/mods/default/sounds/default_sand_footstep.1.ogg new file mode 100644 index 0000000..65b68c7 Binary files /dev/null and b/mods/default/sounds/default_sand_footstep.1.ogg differ diff --git a/mods/default/sounds/default_sand_footstep.2.ogg b/mods/default/sounds/default_sand_footstep.2.ogg new file mode 100644 index 0000000..57f35f3 Binary files /dev/null and b/mods/default/sounds/default_sand_footstep.2.ogg differ diff --git a/mods/default/sounds/default_snow_footstep.1.ogg b/mods/default/sounds/default_snow_footstep.1.ogg new file mode 100644 index 0000000..97cc825 Binary files /dev/null and b/mods/default/sounds/default_snow_footstep.1.ogg differ diff --git a/mods/default/sounds/default_snow_footstep.2.ogg b/mods/default/sounds/default_snow_footstep.2.ogg new file mode 100644 index 0000000..97a6baa Binary files /dev/null and b/mods/default/sounds/default_snow_footstep.2.ogg differ diff --git a/mods/default/sounds/default_snow_footstep.3.ogg b/mods/default/sounds/default_snow_footstep.3.ogg new file mode 100644 index 0000000..bde1f21 Binary files /dev/null and b/mods/default/sounds/default_snow_footstep.3.ogg differ diff --git a/mods/default/sounds/default_snow_footstep.4.ogg b/mods/default/sounds/default_snow_footstep.4.ogg new file mode 100644 index 0000000..8ca6a59 Binary files /dev/null and b/mods/default/sounds/default_snow_footstep.4.ogg differ diff --git a/mods/default/sounds/default_snow_footstep.5.ogg b/mods/default/sounds/default_snow_footstep.5.ogg new file mode 100644 index 0000000..220d60c Binary files /dev/null and b/mods/default/sounds/default_snow_footstep.5.ogg differ diff --git a/mods/default/sounds/default_tool_breaks.1.ogg b/mods/default/sounds/default_tool_breaks.1.ogg new file mode 100644 index 0000000..2a571ae Binary files /dev/null and b/mods/default/sounds/default_tool_breaks.1.ogg differ diff --git a/mods/default/sounds/default_tool_breaks.2.ogg b/mods/default/sounds/default_tool_breaks.2.ogg new file mode 100644 index 0000000..1789352 Binary files /dev/null and b/mods/default/sounds/default_tool_breaks.2.ogg differ diff --git a/mods/default/sounds/default_tool_breaks.3.ogg b/mods/default/sounds/default_tool_breaks.3.ogg new file mode 100644 index 0000000..a99c4b7 Binary files /dev/null and b/mods/default/sounds/default_tool_breaks.3.ogg differ diff --git a/mods/default/sounds/default_water_footstep.1.ogg b/mods/default/sounds/default_water_footstep.1.ogg new file mode 100644 index 0000000..63b9744 Binary files /dev/null and b/mods/default/sounds/default_water_footstep.1.ogg differ diff --git a/mods/default/sounds/default_water_footstep.2.ogg b/mods/default/sounds/default_water_footstep.2.ogg new file mode 100644 index 0000000..8d79c1f Binary files /dev/null and b/mods/default/sounds/default_water_footstep.2.ogg differ diff --git a/mods/default/sounds/default_water_footstep.3.ogg b/mods/default/sounds/default_water_footstep.3.ogg new file mode 100644 index 0000000..f889150 Binary files /dev/null and b/mods/default/sounds/default_water_footstep.3.ogg differ diff --git a/mods/default/sounds/default_water_footstep.4.ogg b/mods/default/sounds/default_water_footstep.4.ogg new file mode 100644 index 0000000..6f1eab8 Binary files /dev/null and b/mods/default/sounds/default_water_footstep.4.ogg differ diff --git a/mods/default/sounds/default_wood_footstep.1.ogg b/mods/default/sounds/default_wood_footstep.1.ogg new file mode 100644 index 0000000..34f63a1 Binary files /dev/null and b/mods/default/sounds/default_wood_footstep.1.ogg differ diff --git a/mods/default/sounds/default_wood_footstep.2.ogg b/mods/default/sounds/default_wood_footstep.2.ogg new file mode 100644 index 0000000..124fc29 Binary files /dev/null and b/mods/default/sounds/default_wood_footstep.2.ogg differ diff --git a/mods/default/textures/bubble.png b/mods/default/textures/bubble.png new file mode 100644 index 0000000..100fe15 Binary files /dev/null and b/mods/default/textures/bubble.png differ diff --git a/mods/default/textures/crack_anylength.png b/mods/default/textures/crack_anylength.png new file mode 100644 index 0000000..297eced Binary files /dev/null and b/mods/default/textures/crack_anylength.png 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 0000000..940b3aa Binary files /dev/null and b/mods/default/textures/default_acacia_bush_sapling.png differ diff --git a/mods/default/textures/default_acacia_bush_stem.png b/mods/default/textures/default_acacia_bush_stem.png new file mode 100644 index 0000000..2903915 Binary files /dev/null and b/mods/default/textures/default_acacia_bush_stem.png differ diff --git a/mods/default/textures/default_acacia_leaves.png b/mods/default/textures/default_acacia_leaves.png new file mode 100644 index 0000000..626e1b3 Binary files /dev/null and b/mods/default/textures/default_acacia_leaves.png differ diff --git a/mods/default/textures/default_acacia_leaves_simple.png b/mods/default/textures/default_acacia_leaves_simple.png new file mode 100644 index 0000000..3c7015b Binary files /dev/null and b/mods/default/textures/default_acacia_leaves_simple.png differ diff --git a/mods/default/textures/default_acacia_sapling.png b/mods/default/textures/default_acacia_sapling.png new file mode 100644 index 0000000..07170a0 Binary files /dev/null and b/mods/default/textures/default_acacia_sapling.png differ diff --git a/mods/default/textures/default_acacia_tree.png b/mods/default/textures/default_acacia_tree.png new file mode 100644 index 0000000..58bb3c4 Binary files /dev/null and b/mods/default/textures/default_acacia_tree.png differ diff --git a/mods/default/textures/default_acacia_tree_top.png b/mods/default/textures/default_acacia_tree_top.png new file mode 100644 index 0000000..a8a0ce0 Binary files /dev/null and b/mods/default/textures/default_acacia_tree_top.png differ diff --git a/mods/default/textures/default_acacia_wood.png b/mods/default/textures/default_acacia_wood.png new file mode 100644 index 0000000..b5abf1e Binary files /dev/null and b/mods/default/textures/default_acacia_wood.png differ diff --git a/mods/default/textures/default_apple.png b/mods/default/textures/default_apple.png new file mode 100644 index 0000000..7549bfd Binary files /dev/null and b/mods/default/textures/default_apple.png differ diff --git a/mods/default/textures/default_aspen_leaves.png b/mods/default/textures/default_aspen_leaves.png new file mode 100644 index 0000000..7306423 Binary files /dev/null and b/mods/default/textures/default_aspen_leaves.png differ diff --git a/mods/default/textures/default_aspen_sapling.png b/mods/default/textures/default_aspen_sapling.png new file mode 100644 index 0000000..f8d9136 Binary files /dev/null and b/mods/default/textures/default_aspen_sapling.png differ diff --git a/mods/default/textures/default_aspen_tree.png b/mods/default/textures/default_aspen_tree.png new file mode 100644 index 0000000..cfb05fc Binary files /dev/null and b/mods/default/textures/default_aspen_tree.png differ diff --git a/mods/default/textures/default_aspen_tree_top.png b/mods/default/textures/default_aspen_tree_top.png new file mode 100644 index 0000000..fcca038 Binary files /dev/null and b/mods/default/textures/default_aspen_tree_top.png differ diff --git a/mods/default/textures/default_aspen_wood.png b/mods/default/textures/default_aspen_wood.png new file mode 100644 index 0000000..2b584b3 Binary files /dev/null and b/mods/default/textures/default_aspen_wood.png differ diff --git a/mods/default/textures/default_blueberries.png b/mods/default/textures/default_blueberries.png new file mode 100644 index 0000000..1dbb0d6 Binary files /dev/null and b/mods/default/textures/default_blueberries.png differ diff --git a/mods/default/textures/default_blueberry_bush_leaves.png b/mods/default/textures/default_blueberry_bush_leaves.png new file mode 100644 index 0000000..2cd112c Binary files /dev/null and b/mods/default/textures/default_blueberry_bush_leaves.png differ diff --git a/mods/default/textures/default_blueberry_bush_sapling.png b/mods/default/textures/default_blueberry_bush_sapling.png new file mode 100644 index 0000000..5d7393f Binary files /dev/null and b/mods/default/textures/default_blueberry_bush_sapling.png differ diff --git a/mods/default/textures/default_blueberry_overlay.png b/mods/default/textures/default_blueberry_overlay.png new file mode 100644 index 0000000..de9de62 Binary files /dev/null and b/mods/default/textures/default_blueberry_overlay.png differ diff --git a/mods/default/textures/default_book.png b/mods/default/textures/default_book.png new file mode 100644 index 0000000..bcf1e6a Binary files /dev/null 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 new file mode 100644 index 0000000..f23d122 Binary files /dev/null and b/mods/default/textures/default_book_written.png differ diff --git a/mods/default/textures/default_bookshelf.png b/mods/default/textures/default_bookshelf.png new file mode 100644 index 0000000..10d6483 Binary files /dev/null and b/mods/default/textures/default_bookshelf.png differ diff --git a/mods/default/textures/default_bookshelf_slot.png b/mods/default/textures/default_bookshelf_slot.png new file mode 100644 index 0000000..cd2c8bc Binary files /dev/null and b/mods/default/textures/default_bookshelf_slot.png differ diff --git a/mods/default/textures/default_brick.png b/mods/default/textures/default_brick.png new file mode 100644 index 0000000..ab19121 Binary files /dev/null and b/mods/default/textures/default_brick.png differ diff --git a/mods/default/textures/default_bronze_block.png b/mods/default/textures/default_bronze_block.png new file mode 100644 index 0000000..1d0c9d5 Binary files /dev/null and b/mods/default/textures/default_bronze_block.png differ diff --git a/mods/default/textures/default_bronze_ingot.png b/mods/default/textures/default_bronze_ingot.png new file mode 100644 index 0000000..6cccdf6 Binary files /dev/null and b/mods/default/textures/default_bronze_ingot.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 0000000..905ba4b Binary files /dev/null and b/mods/default/textures/default_bush_sapling.png differ diff --git a/mods/default/textures/default_bush_stem.png b/mods/default/textures/default_bush_stem.png new file mode 100644 index 0000000..18b615f Binary files /dev/null and b/mods/default/textures/default_bush_stem.png differ diff --git a/mods/default/textures/default_cactus_side.png b/mods/default/textures/default_cactus_side.png new file mode 100644 index 0000000..8d6c40c Binary files /dev/null and b/mods/default/textures/default_cactus_side.png differ diff --git a/mods/default/textures/default_cactus_top.png b/mods/default/textures/default_cactus_top.png new file mode 100644 index 0000000..cf46aa2 Binary files /dev/null and b/mods/default/textures/default_cactus_top.png differ diff --git a/mods/default/textures/default_chest_front.png b/mods/default/textures/default_chest_front.png new file mode 100644 index 0000000..85227d8 Binary files /dev/null and b/mods/default/textures/default_chest_front.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 0000000..5f7b6b1 Binary files /dev/null and b/mods/default/textures/default_chest_inside.png differ diff --git a/mods/default/textures/default_chest_lock.png b/mods/default/textures/default_chest_lock.png new file mode 100644 index 0000000..73f46c7 Binary files /dev/null and b/mods/default/textures/default_chest_lock.png differ diff --git a/mods/default/textures/default_chest_side.png b/mods/default/textures/default_chest_side.png new file mode 100644 index 0000000..44a65a4 Binary files /dev/null and b/mods/default/textures/default_chest_side.png differ diff --git a/mods/default/textures/default_chest_top.png b/mods/default/textures/default_chest_top.png new file mode 100644 index 0000000..f4a92ee Binary files /dev/null and b/mods/default/textures/default_chest_top.png differ diff --git a/mods/default/textures/default_clay.png b/mods/default/textures/default_clay.png new file mode 100644 index 0000000..76e5a40 Binary files /dev/null and b/mods/default/textures/default_clay.png differ diff --git a/mods/default/textures/default_clay_brick.png b/mods/default/textures/default_clay_brick.png new file mode 100644 index 0000000..b288ef0 Binary files /dev/null and b/mods/default/textures/default_clay_brick.png differ diff --git a/mods/default/textures/default_clay_lump.png b/mods/default/textures/default_clay_lump.png new file mode 100644 index 0000000..c1d0220 Binary files /dev/null and b/mods/default/textures/default_clay_lump.png differ diff --git a/mods/default/textures/default_cloud.png b/mods/default/textures/default_cloud.png new file mode 100644 index 0000000..faf0ec1 Binary files /dev/null and b/mods/default/textures/default_cloud.png differ diff --git a/mods/default/textures/default_coal_block.png b/mods/default/textures/default_coal_block.png new file mode 100644 index 0000000..6fe9ed9 Binary files /dev/null and b/mods/default/textures/default_coal_block.png differ diff --git a/mods/default/textures/default_coal_lump.png b/mods/default/textures/default_coal_lump.png new file mode 100644 index 0000000..792961d Binary files /dev/null and b/mods/default/textures/default_coal_lump.png differ diff --git a/mods/default/textures/default_cobble.png b/mods/default/textures/default_cobble.png new file mode 100644 index 0000000..d379840 Binary files /dev/null and b/mods/default/textures/default_cobble.png differ diff --git a/mods/default/textures/default_coniferous_litter.png b/mods/default/textures/default_coniferous_litter.png new file mode 100644 index 0000000..da340e0 Binary files /dev/null and b/mods/default/textures/default_coniferous_litter.png differ diff --git a/mods/default/textures/default_coniferous_litter_side.png b/mods/default/textures/default_coniferous_litter_side.png new file mode 100644 index 0000000..0701461 Binary files /dev/null and b/mods/default/textures/default_coniferous_litter_side.png differ diff --git a/mods/default/textures/default_copper_block.png b/mods/default/textures/default_copper_block.png new file mode 100644 index 0000000..8533754 Binary files /dev/null and b/mods/default/textures/default_copper_block.png differ diff --git a/mods/default/textures/default_copper_ingot.png b/mods/default/textures/default_copper_ingot.png new file mode 100644 index 0000000..bcad9c0 Binary files /dev/null and b/mods/default/textures/default_copper_ingot.png differ diff --git a/mods/default/textures/default_copper_lump.png b/mods/default/textures/default_copper_lump.png new file mode 100644 index 0000000..998c592 Binary files /dev/null and b/mods/default/textures/default_copper_lump.png differ diff --git a/mods/default/textures/default_coral_brown.png b/mods/default/textures/default_coral_brown.png new file mode 100644 index 0000000..8a775fe Binary files /dev/null and b/mods/default/textures/default_coral_brown.png differ diff --git a/mods/default/textures/default_coral_cyan.png b/mods/default/textures/default_coral_cyan.png new file mode 100644 index 0000000..11cc7bf Binary files /dev/null and b/mods/default/textures/default_coral_cyan.png differ diff --git a/mods/default/textures/default_coral_green.png b/mods/default/textures/default_coral_green.png new file mode 100644 index 0000000..847c572 Binary files /dev/null and b/mods/default/textures/default_coral_green.png differ diff --git a/mods/default/textures/default_coral_orange.png b/mods/default/textures/default_coral_orange.png new file mode 100644 index 0000000..cefac62 Binary files /dev/null and b/mods/default/textures/default_coral_orange.png differ diff --git a/mods/default/textures/default_coral_pink.png b/mods/default/textures/default_coral_pink.png new file mode 100644 index 0000000..62d70c6 Binary files /dev/null and b/mods/default/textures/default_coral_pink.png differ diff --git a/mods/default/textures/default_coral_skeleton.png b/mods/default/textures/default_coral_skeleton.png new file mode 100644 index 0000000..fa48f15 Binary files /dev/null and b/mods/default/textures/default_coral_skeleton.png differ diff --git a/mods/default/textures/default_desert_cobble.png b/mods/default/textures/default_desert_cobble.png new file mode 100644 index 0000000..fa1af5d Binary files /dev/null and b/mods/default/textures/default_desert_cobble.png differ diff --git a/mods/default/textures/default_desert_sand.png b/mods/default/textures/default_desert_sand.png new file mode 100644 index 0000000..371b8c7 Binary files /dev/null and b/mods/default/textures/default_desert_sand.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 0000000..52e445f 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 0000000..8fc54e7 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 0000000..ab58db5 Binary files /dev/null and b/mods/default/textures/default_desert_sandstone_brick.png differ diff --git a/mods/default/textures/default_desert_stone.png b/mods/default/textures/default_desert_stone.png new file mode 100644 index 0000000..5d3aded Binary files /dev/null and b/mods/default/textures/default_desert_stone.png differ diff --git a/mods/default/textures/default_desert_stone_block.png b/mods/default/textures/default_desert_stone_block.png new file mode 100644 index 0000000..9eb8e92 Binary files /dev/null and b/mods/default/textures/default_desert_stone_block.png differ diff --git a/mods/default/textures/default_desert_stone_brick.png b/mods/default/textures/default_desert_stone_brick.png new file mode 100644 index 0000000..a603d18 Binary files /dev/null and b/mods/default/textures/default_desert_stone_brick.png differ diff --git a/mods/default/textures/default_diamond.png b/mods/default/textures/default_diamond.png new file mode 100644 index 0000000..a8dac74 Binary files /dev/null and b/mods/default/textures/default_diamond.png differ diff --git a/mods/default/textures/default_diamond_block.png b/mods/default/textures/default_diamond_block.png new file mode 100644 index 0000000..20c33ed Binary files /dev/null and b/mods/default/textures/default_diamond_block.png differ diff --git a/mods/default/textures/default_dirt.png b/mods/default/textures/default_dirt.png new file mode 100644 index 0000000..afe4a2e Binary files /dev/null and b/mods/default/textures/default_dirt.png differ diff --git a/mods/default/textures/default_dry_grass.png b/mods/default/textures/default_dry_grass.png new file mode 100644 index 0000000..03455c3 Binary files /dev/null and b/mods/default/textures/default_dry_grass.png differ diff --git a/mods/default/textures/default_dry_grass_1.png b/mods/default/textures/default_dry_grass_1.png new file mode 100644 index 0000000..5cf68a3 Binary files /dev/null and b/mods/default/textures/default_dry_grass_1.png differ diff --git a/mods/default/textures/default_dry_grass_2.png b/mods/default/textures/default_dry_grass_2.png new file mode 100644 index 0000000..c925ace Binary files /dev/null and b/mods/default/textures/default_dry_grass_2.png differ diff --git a/mods/default/textures/default_dry_grass_3.png b/mods/default/textures/default_dry_grass_3.png new file mode 100644 index 0000000..4e4d84e Binary files /dev/null and b/mods/default/textures/default_dry_grass_3.png differ diff --git a/mods/default/textures/default_dry_grass_4.png b/mods/default/textures/default_dry_grass_4.png new file mode 100644 index 0000000..d315849 Binary files /dev/null and b/mods/default/textures/default_dry_grass_4.png differ diff --git a/mods/default/textures/default_dry_grass_5.png b/mods/default/textures/default_dry_grass_5.png new file mode 100644 index 0000000..871d04c Binary files /dev/null and b/mods/default/textures/default_dry_grass_5.png differ diff --git a/mods/default/textures/default_dry_grass_side.png b/mods/default/textures/default_dry_grass_side.png new file mode 100644 index 0000000..ef375b7 Binary files /dev/null and b/mods/default/textures/default_dry_grass_side.png differ diff --git a/mods/default/textures/default_dry_shrub.png b/mods/default/textures/default_dry_shrub.png new file mode 100644 index 0000000..e8a7f27 Binary files /dev/null and b/mods/default/textures/default_dry_shrub.png differ diff --git a/mods/default/textures/default_emergent_jungle_sapling.png b/mods/default/textures/default_emergent_jungle_sapling.png new file mode 100644 index 0000000..b363b3c Binary files /dev/null and b/mods/default/textures/default_emergent_jungle_sapling.png differ diff --git a/mods/default/textures/default_fence_acacia_wood.png b/mods/default/textures/default_fence_acacia_wood.png new file mode 100644 index 0000000..3b973f3 Binary files /dev/null and b/mods/default/textures/default_fence_acacia_wood.png differ diff --git a/mods/default/textures/default_fence_aspen_wood.png b/mods/default/textures/default_fence_aspen_wood.png new file mode 100644 index 0000000..0a6558e Binary files /dev/null and b/mods/default/textures/default_fence_aspen_wood.png differ diff --git a/mods/default/textures/default_fence_junglewood.png b/mods/default/textures/default_fence_junglewood.png new file mode 100644 index 0000000..c390941 Binary files /dev/null and b/mods/default/textures/default_fence_junglewood.png differ diff --git a/mods/default/textures/default_fence_overlay.png b/mods/default/textures/default_fence_overlay.png new file mode 100644 index 0000000..718184c Binary files /dev/null and b/mods/default/textures/default_fence_overlay.png differ diff --git a/mods/default/textures/default_fence_pine_wood.png b/mods/default/textures/default_fence_pine_wood.png new file mode 100644 index 0000000..74609d9 Binary files /dev/null and b/mods/default/textures/default_fence_pine_wood.png differ diff --git a/mods/default/textures/default_fence_rail_acacia_wood.png b/mods/default/textures/default_fence_rail_acacia_wood.png new file mode 100644 index 0000000..64dc90f Binary files /dev/null and b/mods/default/textures/default_fence_rail_acacia_wood.png differ diff --git a/mods/default/textures/default_fence_rail_aspen_wood.png b/mods/default/textures/default_fence_rail_aspen_wood.png new file mode 100644 index 0000000..ab16a60 Binary files /dev/null and b/mods/default/textures/default_fence_rail_aspen_wood.png differ diff --git a/mods/default/textures/default_fence_rail_junglewood.png b/mods/default/textures/default_fence_rail_junglewood.png new file mode 100644 index 0000000..ebc1ef0 Binary files /dev/null and b/mods/default/textures/default_fence_rail_junglewood.png differ diff --git a/mods/default/textures/default_fence_rail_overlay.png b/mods/default/textures/default_fence_rail_overlay.png new file mode 100644 index 0000000..4da47ae Binary files /dev/null and b/mods/default/textures/default_fence_rail_overlay.png differ diff --git a/mods/default/textures/default_fence_rail_pine_wood.png b/mods/default/textures/default_fence_rail_pine_wood.png new file mode 100644 index 0000000..fd8d99d Binary files /dev/null and b/mods/default/textures/default_fence_rail_pine_wood.png differ diff --git a/mods/default/textures/default_fence_rail_wood.png b/mods/default/textures/default_fence_rail_wood.png new file mode 100644 index 0000000..f84b755 Binary files /dev/null and b/mods/default/textures/default_fence_rail_wood.png differ diff --git a/mods/default/textures/default_fence_wood.png b/mods/default/textures/default_fence_wood.png new file mode 100644 index 0000000..1e76430 Binary files /dev/null and b/mods/default/textures/default_fence_wood.png differ diff --git a/mods/default/textures/default_fern_1.png b/mods/default/textures/default_fern_1.png new file mode 100644 index 0000000..b307986 Binary files /dev/null and b/mods/default/textures/default_fern_1.png differ diff --git a/mods/default/textures/default_fern_2.png b/mods/default/textures/default_fern_2.png new file mode 100644 index 0000000..6c5f7d5 Binary files /dev/null and b/mods/default/textures/default_fern_2.png differ diff --git a/mods/default/textures/default_fern_3.png b/mods/default/textures/default_fern_3.png new file mode 100644 index 0000000..2c1f605 Binary files /dev/null and b/mods/default/textures/default_fern_3.png differ diff --git a/mods/default/textures/default_flint.png b/mods/default/textures/default_flint.png new file mode 100644 index 0000000..226c740 Binary files /dev/null and b/mods/default/textures/default_flint.png differ diff --git a/mods/default/textures/default_footprint.png b/mods/default/textures/default_footprint.png new file mode 100644 index 0000000..41d9546 Binary files /dev/null and b/mods/default/textures/default_footprint.png differ diff --git a/mods/default/textures/default_furnace_bottom.png b/mods/default/textures/default_furnace_bottom.png new file mode 100644 index 0000000..b79ed06 Binary files /dev/null and b/mods/default/textures/default_furnace_bottom.png differ diff --git a/mods/default/textures/default_furnace_fire_bg.png b/mods/default/textures/default_furnace_fire_bg.png new file mode 100644 index 0000000..126204a Binary files /dev/null and b/mods/default/textures/default_furnace_fire_bg.png differ diff --git a/mods/default/textures/default_furnace_fire_fg.png b/mods/default/textures/default_furnace_fire_fg.png new file mode 100644 index 0000000..63888f3 Binary files /dev/null and b/mods/default/textures/default_furnace_fire_fg.png differ diff --git a/mods/default/textures/default_furnace_front.png b/mods/default/textures/default_furnace_front.png new file mode 100644 index 0000000..8c1798e Binary files /dev/null and b/mods/default/textures/default_furnace_front.png differ diff --git a/mods/default/textures/default_furnace_front_active.png b/mods/default/textures/default_furnace_front_active.png new file mode 100644 index 0000000..ea43ed9 Binary files /dev/null and b/mods/default/textures/default_furnace_front_active.png differ diff --git a/mods/default/textures/default_furnace_side.png b/mods/default/textures/default_furnace_side.png new file mode 100644 index 0000000..33408cf Binary files /dev/null and b/mods/default/textures/default_furnace_side.png differ diff --git a/mods/default/textures/default_furnace_top.png b/mods/default/textures/default_furnace_top.png new file mode 100644 index 0000000..b79ed06 Binary files /dev/null and b/mods/default/textures/default_furnace_top.png differ diff --git a/mods/default/textures/default_glass.png b/mods/default/textures/default_glass.png new file mode 100644 index 0000000..74d6a02 Binary files /dev/null and b/mods/default/textures/default_glass.png differ diff --git a/mods/default/textures/default_glass_detail.png b/mods/default/textures/default_glass_detail.png new file mode 100644 index 0000000..811a4db Binary files /dev/null and b/mods/default/textures/default_glass_detail.png differ diff --git a/mods/default/textures/default_gold_block.png b/mods/default/textures/default_gold_block.png new file mode 100644 index 0000000..170d50b Binary files /dev/null and b/mods/default/textures/default_gold_block.png differ diff --git a/mods/default/textures/default_gold_ingot.png b/mods/default/textures/default_gold_ingot.png new file mode 100644 index 0000000..ba66471 Binary files /dev/null and b/mods/default/textures/default_gold_ingot.png differ diff --git a/mods/default/textures/default_gold_lump.png b/mods/default/textures/default_gold_lump.png new file mode 100644 index 0000000..d5a1be7 Binary files /dev/null and b/mods/default/textures/default_gold_lump.png differ diff --git a/mods/default/textures/default_grass.png b/mods/default/textures/default_grass.png new file mode 100644 index 0000000..0181fab Binary files /dev/null and b/mods/default/textures/default_grass.png differ diff --git a/mods/default/textures/default_grass_1.png b/mods/default/textures/default_grass_1.png new file mode 100644 index 0000000..e9faa2c Binary files /dev/null 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 new file mode 100644 index 0000000..03729a0 Binary files /dev/null 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 new file mode 100644 index 0000000..92ca1b5 Binary files /dev/null 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 new file mode 100644 index 0000000..c782a33 Binary files /dev/null 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 new file mode 100644 index 0000000..b727e9c Binary files /dev/null and b/mods/default/textures/default_grass_5.png differ diff --git a/mods/default/textures/default_grass_side.png b/mods/default/textures/default_grass_side.png new file mode 100644 index 0000000..bfd538d Binary files /dev/null and b/mods/default/textures/default_grass_side.png differ diff --git a/mods/default/textures/default_gravel.png b/mods/default/textures/default_gravel.png new file mode 100644 index 0000000..8852d38 Binary files /dev/null and b/mods/default/textures/default_gravel.png differ diff --git a/mods/default/textures/default_ice.png b/mods/default/textures/default_ice.png new file mode 100644 index 0000000..2874e1e Binary files /dev/null and b/mods/default/textures/default_ice.png differ diff --git a/mods/default/textures/default_iron_lump.png b/mods/default/textures/default_iron_lump.png new file mode 100644 index 0000000..db61a94 Binary files /dev/null and b/mods/default/textures/default_iron_lump.png differ diff --git a/mods/default/textures/default_item_smoke.png b/mods/default/textures/default_item_smoke.png new file mode 100644 index 0000000..d62fb3b Binary files /dev/null and b/mods/default/textures/default_item_smoke.png differ diff --git a/mods/default/textures/default_junglegrass.png b/mods/default/textures/default_junglegrass.png new file mode 100644 index 0000000..25abb71 Binary files /dev/null and b/mods/default/textures/default_junglegrass.png differ diff --git a/mods/default/textures/default_jungleleaves.png b/mods/default/textures/default_jungleleaves.png new file mode 100644 index 0000000..5afcc36 Binary files /dev/null and b/mods/default/textures/default_jungleleaves.png differ diff --git a/mods/default/textures/default_jungleleaves_simple.png b/mods/default/textures/default_jungleleaves_simple.png new file mode 100644 index 0000000..7165100 Binary files /dev/null and b/mods/default/textures/default_jungleleaves_simple.png differ diff --git a/mods/default/textures/default_junglesapling.png b/mods/default/textures/default_junglesapling.png new file mode 100644 index 0000000..05e1e50 Binary files /dev/null and b/mods/default/textures/default_junglesapling.png differ diff --git a/mods/default/textures/default_jungletree.png b/mods/default/textures/default_jungletree.png new file mode 100644 index 0000000..2cf77a6 Binary files /dev/null and b/mods/default/textures/default_jungletree.png differ diff --git a/mods/default/textures/default_jungletree_top.png b/mods/default/textures/default_jungletree_top.png new file mode 100644 index 0000000..439f078 Binary files /dev/null and b/mods/default/textures/default_jungletree_top.png differ diff --git a/mods/default/textures/default_junglewood.png b/mods/default/textures/default_junglewood.png new file mode 100644 index 0000000..8d17917 Binary files /dev/null and b/mods/default/textures/default_junglewood.png differ diff --git a/mods/default/textures/default_kelp.png b/mods/default/textures/default_kelp.png new file mode 100644 index 0000000..70b743d Binary files /dev/null and b/mods/default/textures/default_kelp.png differ diff --git a/mods/default/textures/default_key.png b/mods/default/textures/default_key.png new file mode 100644 index 0000000..783d313 Binary files /dev/null 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 new file mode 100644 index 0000000..2b3497d Binary files /dev/null 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 new file mode 100644 index 0000000..a312f3e Binary files /dev/null and b/mods/default/textures/default_ladder_steel.png differ diff --git a/mods/default/textures/default_ladder_wood.png b/mods/default/textures/default_ladder_wood.png new file mode 100644 index 0000000..c167fff Binary files /dev/null and b/mods/default/textures/default_ladder_wood.png differ diff --git a/mods/default/textures/default_lava.png b/mods/default/textures/default_lava.png new file mode 100644 index 0000000..e8958de Binary files /dev/null and b/mods/default/textures/default_lava.png differ diff --git a/mods/default/textures/default_lava_flowing_animated.png b/mods/default/textures/default_lava_flowing_animated.png new file mode 100644 index 0000000..2ec0746 Binary files /dev/null and b/mods/default/textures/default_lava_flowing_animated.png differ diff --git a/mods/default/textures/default_lava_source_animated.png b/mods/default/textures/default_lava_source_animated.png new file mode 100644 index 0000000..32267a6 Binary files /dev/null and b/mods/default/textures/default_lava_source_animated.png differ diff --git a/mods/default/textures/default_leaves.png b/mods/default/textures/default_leaves.png new file mode 100644 index 0000000..ba09fe1 Binary files /dev/null and b/mods/default/textures/default_leaves.png differ diff --git a/mods/default/textures/default_leaves_simple.png b/mods/default/textures/default_leaves_simple.png new file mode 100644 index 0000000..eb60f9f Binary files /dev/null and b/mods/default/textures/default_leaves_simple.png differ diff --git a/mods/default/textures/default_marram_grass_1.png b/mods/default/textures/default_marram_grass_1.png new file mode 100644 index 0000000..73ec9e9 Binary files /dev/null and b/mods/default/textures/default_marram_grass_1.png differ diff --git a/mods/default/textures/default_marram_grass_2.png b/mods/default/textures/default_marram_grass_2.png new file mode 100644 index 0000000..2db75c7 Binary files /dev/null and b/mods/default/textures/default_marram_grass_2.png differ diff --git a/mods/default/textures/default_marram_grass_3.png b/mods/default/textures/default_marram_grass_3.png new file mode 100644 index 0000000..f6c155f Binary files /dev/null and b/mods/default/textures/default_marram_grass_3.png differ diff --git a/mods/default/textures/default_mese_block.png b/mods/default/textures/default_mese_block.png new file mode 100644 index 0000000..e30994e Binary files /dev/null and b/mods/default/textures/default_mese_block.png differ diff --git a/mods/default/textures/default_mese_crystal.png b/mods/default/textures/default_mese_crystal.png new file mode 100644 index 0000000..f1d71f1 Binary files /dev/null and b/mods/default/textures/default_mese_crystal.png differ diff --git a/mods/default/textures/default_mese_crystal_fragment.png b/mods/default/textures/default_mese_crystal_fragment.png new file mode 100644 index 0000000..d5416ab Binary files /dev/null and b/mods/default/textures/default_mese_crystal_fragment.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 0000000..c23b551 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 0000000..c4fc7ce 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 0000000..365c1a7 Binary files /dev/null and b/mods/default/textures/default_mese_post_light_top.png differ diff --git a/mods/default/textures/default_meselamp.png b/mods/default/textures/default_meselamp.png new file mode 100644 index 0000000..0c3a1a1 Binary files /dev/null and b/mods/default/textures/default_meselamp.png differ diff --git a/mods/default/textures/default_mineral_coal.png b/mods/default/textures/default_mineral_coal.png new file mode 100644 index 0000000..6d1386b Binary files /dev/null and b/mods/default/textures/default_mineral_coal.png differ diff --git a/mods/default/textures/default_mineral_copper.png b/mods/default/textures/default_mineral_copper.png new file mode 100644 index 0000000..c4c518e Binary files /dev/null and b/mods/default/textures/default_mineral_copper.png differ diff --git a/mods/default/textures/default_mineral_diamond.png b/mods/default/textures/default_mineral_diamond.png new file mode 100644 index 0000000..39c0f83 Binary files /dev/null and b/mods/default/textures/default_mineral_diamond.png differ diff --git a/mods/default/textures/default_mineral_gold.png b/mods/default/textures/default_mineral_gold.png new file mode 100644 index 0000000..2220add Binary files /dev/null and b/mods/default/textures/default_mineral_gold.png differ diff --git a/mods/default/textures/default_mineral_iron.png b/mods/default/textures/default_mineral_iron.png new file mode 100644 index 0000000..bfec8b1 Binary files /dev/null and b/mods/default/textures/default_mineral_iron.png differ diff --git a/mods/default/textures/default_mineral_mese.png b/mods/default/textures/default_mineral_mese.png new file mode 100644 index 0000000..6952670 Binary files /dev/null and b/mods/default/textures/default_mineral_mese.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 0000000..232d4b5 Binary files /dev/null and b/mods/default/textures/default_mineral_tin.png differ diff --git a/mods/default/textures/default_moss.png b/mods/default/textures/default_moss.png new file mode 100644 index 0000000..479038e Binary files /dev/null and b/mods/default/textures/default_moss.png differ diff --git a/mods/default/textures/default_moss_side.png b/mods/default/textures/default_moss_side.png new file mode 100644 index 0000000..4a20345 Binary files /dev/null and b/mods/default/textures/default_moss_side.png differ diff --git a/mods/default/textures/default_mossycobble.png b/mods/default/textures/default_mossycobble.png new file mode 100644 index 0000000..1ae7c91 Binary files /dev/null and b/mods/default/textures/default_mossycobble.png differ diff --git a/mods/default/textures/default_obsidian.png b/mods/default/textures/default_obsidian.png new file mode 100644 index 0000000..8f4a49c Binary files /dev/null and b/mods/default/textures/default_obsidian.png differ diff --git a/mods/default/textures/default_obsidian_block.png b/mods/default/textures/default_obsidian_block.png new file mode 100644 index 0000000..7e1d4d3 Binary files /dev/null and b/mods/default/textures/default_obsidian_block.png differ diff --git a/mods/default/textures/default_obsidian_brick.png b/mods/default/textures/default_obsidian_brick.png new file mode 100644 index 0000000..30c67ca Binary files /dev/null and b/mods/default/textures/default_obsidian_brick.png differ diff --git a/mods/default/textures/default_obsidian_glass.png b/mods/default/textures/default_obsidian_glass.png new file mode 100644 index 0000000..d5ac83d Binary files /dev/null and b/mods/default/textures/default_obsidian_glass.png differ diff --git a/mods/default/textures/default_obsidian_glass_detail.png b/mods/default/textures/default_obsidian_glass_detail.png new file mode 100644 index 0000000..a8bbec9 Binary files /dev/null and b/mods/default/textures/default_obsidian_glass_detail.png differ diff --git a/mods/default/textures/default_obsidian_shard.png b/mods/default/textures/default_obsidian_shard.png new file mode 100644 index 0000000..a988d8c Binary files /dev/null and b/mods/default/textures/default_obsidian_shard.png differ diff --git a/mods/default/textures/default_paper.png b/mods/default/textures/default_paper.png new file mode 100644 index 0000000..8f23924 Binary files /dev/null and b/mods/default/textures/default_paper.png differ diff --git a/mods/default/textures/default_papyrus.png b/mods/default/textures/default_papyrus.png new file mode 100644 index 0000000..a85e809 Binary files /dev/null and b/mods/default/textures/default_papyrus.png differ diff --git a/mods/default/textures/default_permafrost.png b/mods/default/textures/default_permafrost.png new file mode 100644 index 0000000..f1edbab Binary files /dev/null and b/mods/default/textures/default_permafrost.png differ diff --git a/mods/default/textures/default_pine_bush_sapling.png b/mods/default/textures/default_pine_bush_sapling.png new file mode 100644 index 0000000..fadeff8 Binary files /dev/null and b/mods/default/textures/default_pine_bush_sapling.png differ diff --git a/mods/default/textures/default_pine_bush_stem.png b/mods/default/textures/default_pine_bush_stem.png new file mode 100644 index 0000000..e239f81 Binary files /dev/null and b/mods/default/textures/default_pine_bush_stem.png differ diff --git a/mods/default/textures/default_pine_needles.png b/mods/default/textures/default_pine_needles.png new file mode 100644 index 0000000..f699727 Binary files /dev/null and b/mods/default/textures/default_pine_needles.png differ diff --git a/mods/default/textures/default_pine_sapling.png b/mods/default/textures/default_pine_sapling.png new file mode 100644 index 0000000..c30131d Binary files /dev/null and b/mods/default/textures/default_pine_sapling.png differ diff --git a/mods/default/textures/default_pine_tree.png b/mods/default/textures/default_pine_tree.png new file mode 100644 index 0000000..4a5328f Binary files /dev/null and b/mods/default/textures/default_pine_tree.png differ diff --git a/mods/default/textures/default_pine_tree_top.png b/mods/default/textures/default_pine_tree_top.png new file mode 100644 index 0000000..8705710 Binary files /dev/null and b/mods/default/textures/default_pine_tree_top.png differ diff --git a/mods/default/textures/default_pine_wood.png b/mods/default/textures/default_pine_wood.png new file mode 100644 index 0000000..6844ceb Binary files /dev/null and b/mods/default/textures/default_pine_wood.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 0000000..d762deb 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 0000000..7ccb11d Binary files /dev/null and b/mods/default/textures/default_rainforest_litter_side.png differ diff --git a/mods/default/textures/default_river_water.png b/mods/default/textures/default_river_water.png new file mode 100644 index 0000000..3b55c5f Binary files /dev/null and b/mods/default/textures/default_river_water.png differ diff --git a/mods/default/textures/default_river_water_flowing_animated.png b/mods/default/textures/default_river_water_flowing_animated.png new file mode 100644 index 0000000..536acc5 Binary files /dev/null and b/mods/default/textures/default_river_water_flowing_animated.png differ diff --git a/mods/default/textures/default_river_water_source_animated.png b/mods/default/textures/default_river_water_source_animated.png new file mode 100644 index 0000000..daa5653 Binary files /dev/null and b/mods/default/textures/default_river_water_source_animated.png differ diff --git a/mods/default/textures/default_sand.png b/mods/default/textures/default_sand.png new file mode 100644 index 0000000..645a300 Binary files /dev/null and b/mods/default/textures/default_sand.png differ diff --git a/mods/default/textures/default_sandstone.png b/mods/default/textures/default_sandstone.png new file mode 100644 index 0000000..16e3d13 Binary files /dev/null and b/mods/default/textures/default_sandstone.png differ diff --git a/mods/default/textures/default_sandstone_block.png b/mods/default/textures/default_sandstone_block.png new file mode 100644 index 0000000..2e06491 Binary files /dev/null and b/mods/default/textures/default_sandstone_block.png differ diff --git a/mods/default/textures/default_sandstone_brick.png b/mods/default/textures/default_sandstone_brick.png new file mode 100644 index 0000000..e7150e5 Binary files /dev/null and b/mods/default/textures/default_sandstone_brick.png differ diff --git a/mods/default/textures/default_sapling.png b/mods/default/textures/default_sapling.png new file mode 100644 index 0000000..3fd64f0 Binary files /dev/null and b/mods/default/textures/default_sapling.png differ diff --git a/mods/default/textures/default_sign_steel.png b/mods/default/textures/default_sign_steel.png new file mode 100644 index 0000000..3ca0c59 Binary files /dev/null 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 new file mode 100644 index 0000000..2227477 Binary files /dev/null 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 new file mode 100644 index 0000000..40552c7 Binary files /dev/null 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 new file mode 100644 index 0000000..d0559da Binary files /dev/null and b/mods/default/textures/default_sign_wood.png differ diff --git a/mods/default/textures/default_silver_sand.png b/mods/default/textures/default_silver_sand.png new file mode 100644 index 0000000..c4a8f73 Binary files /dev/null and b/mods/default/textures/default_silver_sand.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 0000000..eac62cb 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 0000000..9997461 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 0000000..93d87a5 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 new file mode 100644 index 0000000..fcbef0e Binary files /dev/null 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 new file mode 100644 index 0000000..03456c8 Binary files /dev/null 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 new file mode 100644 index 0000000..3a4dc1f Binary files /dev/null and b/mods/default/textures/default_snowball.png differ diff --git a/mods/default/textures/default_steel_block.png b/mods/default/textures/default_steel_block.png new file mode 100644 index 0000000..7f49f61 Binary files /dev/null and b/mods/default/textures/default_steel_block.png differ diff --git a/mods/default/textures/default_steel_ingot.png b/mods/default/textures/default_steel_ingot.png new file mode 100644 index 0000000..8100b01 Binary files /dev/null and b/mods/default/textures/default_steel_ingot.png differ diff --git a/mods/default/textures/default_stick.png b/mods/default/textures/default_stick.png new file mode 100644 index 0000000..0378d07 Binary files /dev/null and b/mods/default/textures/default_stick.png differ diff --git a/mods/default/textures/default_stone.png b/mods/default/textures/default_stone.png new file mode 100644 index 0000000..63cb7c4 Binary files /dev/null and b/mods/default/textures/default_stone.png differ diff --git a/mods/default/textures/default_stone_block.png b/mods/default/textures/default_stone_block.png new file mode 100644 index 0000000..3b771e7 Binary files /dev/null and b/mods/default/textures/default_stone_block.png differ diff --git a/mods/default/textures/default_stone_brick.png b/mods/default/textures/default_stone_brick.png new file mode 100644 index 0000000..4dbb49d Binary files /dev/null and b/mods/default/textures/default_stone_brick.png differ diff --git a/mods/default/textures/default_stones.png b/mods/default/textures/default_stones.png new file mode 100644 index 0000000..09c5ee1 Binary files /dev/null and b/mods/default/textures/default_stones.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 0000000..72759b0 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 0000000..eed5361 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 0000000..72bd339 Binary files /dev/null and b/mods/default/textures/default_tin_lump.png differ diff --git a/mods/default/textures/default_tool_bronzeaxe.png b/mods/default/textures/default_tool_bronzeaxe.png new file mode 100644 index 0000000..8ae43b5 Binary files /dev/null and b/mods/default/textures/default_tool_bronzeaxe.png differ diff --git a/mods/default/textures/default_tool_bronzepick.png b/mods/default/textures/default_tool_bronzepick.png new file mode 100644 index 0000000..c88a5f0 Binary files /dev/null and b/mods/default/textures/default_tool_bronzepick.png differ diff --git a/mods/default/textures/default_tool_bronzeshovel.png b/mods/default/textures/default_tool_bronzeshovel.png new file mode 100644 index 0000000..d7d800e Binary files /dev/null and b/mods/default/textures/default_tool_bronzeshovel.png differ diff --git a/mods/default/textures/default_tool_bronzesword.png b/mods/default/textures/default_tool_bronzesword.png new file mode 100644 index 0000000..cdab898 Binary files /dev/null and b/mods/default/textures/default_tool_bronzesword.png differ diff --git a/mods/default/textures/default_tool_diamondaxe.png b/mods/default/textures/default_tool_diamondaxe.png new file mode 100644 index 0000000..e32a0bf Binary files /dev/null and b/mods/default/textures/default_tool_diamondaxe.png differ diff --git a/mods/default/textures/default_tool_diamondpick.png b/mods/default/textures/default_tool_diamondpick.png new file mode 100644 index 0000000..f9883c6 Binary files /dev/null and b/mods/default/textures/default_tool_diamondpick.png differ diff --git a/mods/default/textures/default_tool_diamondshovel.png b/mods/default/textures/default_tool_diamondshovel.png new file mode 100644 index 0000000..d0fe24d Binary files /dev/null and b/mods/default/textures/default_tool_diamondshovel.png differ diff --git a/mods/default/textures/default_tool_diamondsword.png b/mods/default/textures/default_tool_diamondsword.png new file mode 100644 index 0000000..dbccd0e Binary files /dev/null and b/mods/default/textures/default_tool_diamondsword.png differ diff --git a/mods/default/textures/default_tool_meseaxe.png b/mods/default/textures/default_tool_meseaxe.png new file mode 100644 index 0000000..c01fb4f Binary files /dev/null and b/mods/default/textures/default_tool_meseaxe.png differ diff --git a/mods/default/textures/default_tool_mesepick.png b/mods/default/textures/default_tool_mesepick.png new file mode 100644 index 0000000..1b2e25b Binary files /dev/null and b/mods/default/textures/default_tool_mesepick.png differ diff --git a/mods/default/textures/default_tool_meseshovel.png b/mods/default/textures/default_tool_meseshovel.png new file mode 100644 index 0000000..00813a2 Binary files /dev/null and b/mods/default/textures/default_tool_meseshovel.png differ diff --git a/mods/default/textures/default_tool_mesesword.png b/mods/default/textures/default_tool_mesesword.png new file mode 100644 index 0000000..d395d3a Binary files /dev/null and b/mods/default/textures/default_tool_mesesword.png differ diff --git a/mods/default/textures/default_tool_steelaxe.png b/mods/default/textures/default_tool_steelaxe.png new file mode 100644 index 0000000..1528cad Binary files /dev/null and b/mods/default/textures/default_tool_steelaxe.png differ diff --git a/mods/default/textures/default_tool_steelpick.png b/mods/default/textures/default_tool_steelpick.png new file mode 100644 index 0000000..a7543a1 Binary files /dev/null and b/mods/default/textures/default_tool_steelpick.png differ diff --git a/mods/default/textures/default_tool_steelshovel.png b/mods/default/textures/default_tool_steelshovel.png new file mode 100644 index 0000000..65e4045 Binary files /dev/null and b/mods/default/textures/default_tool_steelshovel.png differ diff --git a/mods/default/textures/default_tool_steelsword.png b/mods/default/textures/default_tool_steelsword.png new file mode 100644 index 0000000..630a339 Binary files /dev/null and b/mods/default/textures/default_tool_steelsword.png differ diff --git a/mods/default/textures/default_tool_stoneaxe.png b/mods/default/textures/default_tool_stoneaxe.png new file mode 100644 index 0000000..cc36054 Binary files /dev/null and b/mods/default/textures/default_tool_stoneaxe.png differ diff --git a/mods/default/textures/default_tool_stonepick.png b/mods/default/textures/default_tool_stonepick.png new file mode 100644 index 0000000..237d739 Binary files /dev/null and b/mods/default/textures/default_tool_stonepick.png differ diff --git a/mods/default/textures/default_tool_stoneshovel.png b/mods/default/textures/default_tool_stoneshovel.png new file mode 100644 index 0000000..11711bd Binary files /dev/null and b/mods/default/textures/default_tool_stoneshovel.png differ diff --git a/mods/default/textures/default_tool_stonesword.png b/mods/default/textures/default_tool_stonesword.png new file mode 100644 index 0000000..1a493ac Binary files /dev/null and b/mods/default/textures/default_tool_stonesword.png differ diff --git a/mods/default/textures/default_tool_woodaxe.png b/mods/default/textures/default_tool_woodaxe.png new file mode 100644 index 0000000..68f1fd8 Binary files /dev/null and b/mods/default/textures/default_tool_woodaxe.png differ diff --git a/mods/default/textures/default_tool_woodpick.png b/mods/default/textures/default_tool_woodpick.png new file mode 100644 index 0000000..0aed583 Binary files /dev/null and b/mods/default/textures/default_tool_woodpick.png differ diff --git a/mods/default/textures/default_tool_woodshovel.png b/mods/default/textures/default_tool_woodshovel.png new file mode 100644 index 0000000..dcef2b5 Binary files /dev/null and b/mods/default/textures/default_tool_woodshovel.png differ diff --git a/mods/default/textures/default_tool_woodsword.png b/mods/default/textures/default_tool_woodsword.png new file mode 100644 index 0000000..c78ba50 Binary files /dev/null and b/mods/default/textures/default_tool_woodsword.png differ diff --git a/mods/default/textures/default_torch_animated.png b/mods/default/textures/default_torch_animated.png new file mode 100644 index 0000000..cdf33ef Binary files /dev/null and b/mods/default/textures/default_torch_animated.png differ diff --git a/mods/default/textures/default_torch_on_ceiling_animated.png b/mods/default/textures/default_torch_on_ceiling_animated.png new file mode 100644 index 0000000..3a8b5ad Binary files /dev/null and b/mods/default/textures/default_torch_on_ceiling_animated.png differ diff --git a/mods/default/textures/default_torch_on_floor.png b/mods/default/textures/default_torch_on_floor.png new file mode 100644 index 0000000..bc4bdd6 Binary files /dev/null and b/mods/default/textures/default_torch_on_floor.png differ diff --git a/mods/default/textures/default_torch_on_floor_animated.png b/mods/default/textures/default_torch_on_floor_animated.png new file mode 100644 index 0000000..ad51c03 Binary files /dev/null and b/mods/default/textures/default_torch_on_floor_animated.png differ diff --git a/mods/default/textures/default_tree.png b/mods/default/textures/default_tree.png new file mode 100644 index 0000000..10e297b Binary files /dev/null and b/mods/default/textures/default_tree.png differ diff --git a/mods/default/textures/default_tree_top.png b/mods/default/textures/default_tree_top.png new file mode 100644 index 0000000..da99bce Binary files /dev/null and b/mods/default/textures/default_tree_top.png differ diff --git a/mods/default/textures/default_water.png b/mods/default/textures/default_water.png new file mode 100644 index 0000000..00500e9 Binary files /dev/null and b/mods/default/textures/default_water.png differ diff --git a/mods/default/textures/default_water_flowing_animated.png b/mods/default/textures/default_water_flowing_animated.png new file mode 100644 index 0000000..070d797 Binary files /dev/null and b/mods/default/textures/default_water_flowing_animated.png differ diff --git a/mods/default/textures/default_water_source_animated.png b/mods/default/textures/default_water_source_animated.png new file mode 100644 index 0000000..7e7f9ff Binary files /dev/null and b/mods/default/textures/default_water_source_animated.png differ diff --git a/mods/default/textures/default_wood.png b/mods/default/textures/default_wood.png new file mode 100644 index 0000000..af56d6c Binary files /dev/null and b/mods/default/textures/default_wood.png differ diff --git a/mods/default/textures/gui_formbg.png b/mods/default/textures/gui_formbg.png new file mode 100644 index 0000000..758234e Binary files /dev/null and b/mods/default/textures/gui_formbg.png differ diff --git a/mods/default/textures/gui_furnace_arrow_bg.png b/mods/default/textures/gui_furnace_arrow_bg.png new file mode 100644 index 0000000..046d8cd Binary files /dev/null and b/mods/default/textures/gui_furnace_arrow_bg.png differ diff --git a/mods/default/textures/gui_furnace_arrow_fg.png b/mods/default/textures/gui_furnace_arrow_fg.png new file mode 100644 index 0000000..8d3c396 Binary files /dev/null and b/mods/default/textures/gui_furnace_arrow_fg.png differ diff --git a/mods/default/textures/gui_hb_bg.png b/mods/default/textures/gui_hb_bg.png new file mode 100644 index 0000000..99248e1 Binary files /dev/null and b/mods/default/textures/gui_hb_bg.png differ diff --git a/mods/default/textures/heart.png b/mods/default/textures/heart.png new file mode 100644 index 0000000..6d4e228 Binary files /dev/null and b/mods/default/textures/heart.png differ diff --git a/mods/default/textures/wieldhand.png b/mods/default/textures/wieldhand.png new file mode 100644 index 0000000..69f4b7b Binary files /dev/null and b/mods/default/textures/wieldhand.png differ diff --git a/mods/default/tools.lua b/mods/default/tools.lua new file mode 100644 index 0000000..b8ec07d --- /dev/null +++ b/mods/default/tools.lua @@ -0,0 +1,442 @@ +-- mods/default/tools.lua + +-- The hand +minetest.register_item(":", { + type = "none", + wield_image = "wieldhand.png", + wield_scale = {x=1,y=1,z=2.5}, + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level = 0, + groupcaps = { + ---[[ + crumbly = {times={[3]=3.70}, uses=0, maxlevel=1}, + snappy = {times={[3] = 2.40}, uses = 0, maxlevel = 1}, + oddly_breakable_by_hand = {times={[1]=5.50,[2]=4.00,[3]=2.70}, uses=0}, + --]] + }, + damage_groups = {fleshy=1}, + } +}) + +-- +-- Picks +-- + +minetest.register_tool("default:pick_wood", { + description = "Wooden Pickaxe", + inventory_image = "default_tool_woodpick.png", + tool_capabilities = { + full_punch_interval = 1.2, + max_drop_level=0, + groupcaps={ + cracky = {times={[3]=1.60}, uses=10, maxlevel=1}, + }, + damage_groups = {fleshy=2}, + }, + groups = {flammable = 2, tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:pick_stone", { + description = "Stone Pickaxe", + inventory_image = "default_tool_stonepick.png", + tool_capabilities = { + full_punch_interval = 1.3, + max_drop_level=0, + groupcaps={ + cracky = {times={[2]=2.0, [3]=1.00}, uses=20, maxlevel=1}, + }, + damage_groups = {fleshy=3}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:pick_bronze", { + description = "Bronze Pickaxe", + inventory_image = "default_tool_bronzepick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + cracky = {times={[1]=4.50, [2]=1.80, [3]=0.90}, uses=20, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:pick_steel", { + description = "Steel Pickaxe", + inventory_image = "default_tool_steelpick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + cracky = {times={[1]=4.00, [2]=1.60, [3]=0.80}, uses=20, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:pick_mese", { + description = "Mese Pickaxe", + inventory_image = "default_tool_mesepick.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky = {times={[1]=2.4, [2]=1.2, [3]=0.60}, uses=20, maxlevel=3}, + }, + damage_groups = {fleshy=5}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:pick_diamond", { + description = "Diamond Pickaxe", + inventory_image = "default_tool_diamondpick.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky = {times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=30, maxlevel=3}, + }, + damage_groups = {fleshy=5}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +-- +-- Shovels +-- + +minetest.register_tool("default:shovel_wood", { + description = "Wooden Shovel", + inventory_image = "default_tool_woodshovel.png", + wield_image = "default_tool_woodshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.2, + max_drop_level=0, + groupcaps={ + crumbly = {times={[1]=3.00, [2]=1.60, [3]=0.60}, uses=10, maxlevel=1}, + }, + damage_groups = {fleshy=2}, + }, + groups = {flammable = 2, tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:shovel_stone", { + description = "Stone Shovel", + inventory_image = "default_tool_stoneshovel.png", + wield_image = "default_tool_stoneshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.4, + max_drop_level=0, + groupcaps={ + crumbly = {times={[1]=1.80, [2]=1.20, [3]=0.50}, uses=20, maxlevel=1}, + }, + damage_groups = {fleshy=2}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:shovel_bronze", { + description = "Bronze Shovel", + inventory_image = "default_tool_bronzeshovel.png", + wield_image = "default_tool_bronzeshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.1, + max_drop_level=1, + groupcaps={ + crumbly = {times={[1]=1.65, [2]=1.05, [3]=0.45}, uses=25, maxlevel=2}, + }, + damage_groups = {fleshy=3}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:shovel_steel", { + description = "Steel Shovel", + inventory_image = "default_tool_steelshovel.png", + wield_image = "default_tool_steelshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.1, + max_drop_level=1, + groupcaps={ + crumbly = {times={[1]=1.50, [2]=0.90, [3]=0.40}, uses=30, maxlevel=2}, + }, + damage_groups = {fleshy=3}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:shovel_mese", { + description = "Mese Shovel", + inventory_image = "default_tool_meseshovel.png", + wield_image = "default_tool_meseshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=3, + groupcaps={ + crumbly = {times={[1]=1.20, [2]=0.60, [3]=0.30}, uses=20, maxlevel=3}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:shovel_diamond", { + description = "Diamond Shovel", + inventory_image = "default_tool_diamondshovel.png", + wield_image = "default_tool_diamondshovel.png^[transformR90", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + crumbly = {times={[1]=1.10, [2]=0.50, [3]=0.30}, uses=30, maxlevel=3}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +-- +-- Axes +-- + +minetest.register_tool("default:axe_wood", { + description = "Wooden Axe", + inventory_image = "default_tool_woodaxe.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=0, + groupcaps={ + choppy = {times={[2]=3.00, [3]=1.60}, uses=10, maxlevel=1}, + }, + damage_groups = {fleshy=2}, + }, + groups = {flammable = 2, tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:axe_stone", { + description = "Stone Axe", + inventory_image = "default_tool_stoneaxe.png", + tool_capabilities = { + full_punch_interval = 1.2, + max_drop_level=0, + groupcaps={ + choppy={times={[1]=3.00, [2]=2.00, [3]=1.30}, uses=20, maxlevel=1}, + }, + damage_groups = {fleshy=3}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:axe_bronze", { + description = "Bronze Axe", + inventory_image = "default_tool_bronzeaxe.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.75, [2]=1.70, [3]=1.15}, uses=20, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:axe_steel", { + description = "Steel Axe", + inventory_image = "default_tool_steelaxe.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.50, [2]=1.40, [3]=1.00}, uses=20, maxlevel=2}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:axe_mese", { + description = "Mese Axe", + inventory_image = "default_tool_meseaxe.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.20, [2]=1.00, [3]=0.60}, uses=20, maxlevel=3}, + }, + damage_groups = {fleshy=6}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:axe_diamond", { + description = "Diamond Axe", + inventory_image = "default_tool_diamondaxe.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.10, [2]=0.90, [3]=0.50}, uses=30, maxlevel=3}, + }, + damage_groups = {fleshy=7}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +-- +-- Swords +-- + +minetest.register_tool("default:sword_wood", { + description = "Wooden Sword", + inventory_image = "default_tool_woodsword.png", + tool_capabilities = { + full_punch_interval = 1, + max_drop_level=0, + groupcaps={ + snappy={times={[2]=1.6, [3]=0.40}, uses=10, maxlevel=1}, + }, + damage_groups = {fleshy=2}, + }, + groups = {flammable = 2, tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:sword_stone", { + description = "Stone Sword", + inventory_image = "default_tool_stonesword.png", + tool_capabilities = { + full_punch_interval = 1.2, + max_drop_level=0, + groupcaps={ + snappy={times={[2]=1.4, [3]=0.40}, uses=20, maxlevel=1}, + }, + damage_groups = {fleshy=4}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:sword_bronze", { + description = "Bronze Sword", + inventory_image = "default_tool_bronzesword.png", + tool_capabilities = { + full_punch_interval = 0.8, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=2.75, [2]=1.30, [3]=0.375}, uses=25, maxlevel=2}, + }, + damage_groups = {fleshy=6}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:sword_steel", { + description = "Steel Sword", + inventory_image = "default_tool_steelsword.png", + tool_capabilities = { + full_punch_interval = 0.8, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=2.5, [2]=1.20, [3]=0.35}, uses=30, maxlevel=2}, + }, + damage_groups = {fleshy=6}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:sword_mese", { + description = "Mese Sword", + inventory_image = "default_tool_mesesword.png", + tool_capabilities = { + full_punch_interval = 0.7, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=2.0, [2]=1.00, [3]=0.35}, uses=30, maxlevel=3}, + }, + damage_groups = {fleshy=7}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +minetest.register_tool("default:sword_diamond", { + description = "Diamond Sword", + inventory_image = "default_tool_diamondsword.png", + tool_capabilities = { + full_punch_interval = 0.7, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=1.90, [2]=0.90, [3]=0.30}, uses=40, maxlevel=3}, + }, + damage_groups = {fleshy=8}, + }, + groups = {tool = 1}, + sound = {breaks = "default_tool_breaks"}, +}) + +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:is_player() 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 + node = minetest.get_node(pos) + + if not node or node.name == "ignore" then + return itemstack + end + + local ndef = minetest.registered_nodes[node.name] + if not ndef then + return itemstack + end + + local on_key_use = ndef.on_key_use + if on_key_use then + on_key_use(pos, placer) + end + + return nil + end +}) diff --git a/mods/default/torch.lua b/mods/default/torch.lua new file mode 100644 index 0000000..5de5f89 --- /dev/null +++ b/mods/default/torch.lua @@ -0,0 +1,131 @@ +local function on_flood(pos, oldnode, newnode) + minetest.add_item(pos, ItemStack("default:torch 1")) + -- Play flame-extinguish sound if liquid is not an 'igniter' + local nodedef = minetest.registered_items[newnode.name] + if not (nodedef and nodedef.groups and + nodedef.groups.igniter and nodedef.groups.igniter > 0) then + minetest.sound_play( + "default_cool_lava", + {pos = pos, max_hear_distance = 16, gain = 0.1} + ) + end + -- Remove the torch node + return false +end + +minetest.register_node("default:torch", { + description = "Torch", + drawtype = "mesh", + mesh = "torch_floor.obj", + inventory_image = "default_torch_on_floor.png", + wield_image = "default_torch_on_floor.png", + tiles = {{ + name = "default_torch_on_floor_animated.png", + animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3} + }}, + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + liquids_pointable = false, + light_source = 12, + groups = {choppy=2, dig_immediate=3, flammable=1, attached_node=1, torch=1}, + drop = "default:torch", + selection_box = { + type = "wallmounted", + wall_bottom = {-1/8, -1/2, -1/8, 1/8, 2/16, 1/8}, + }, + sounds = default.node_sound_wood_defaults(), + 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:is_player() and + placer:get_player_control().sneak) then + return def.on_rightclick(under, node, placer, itemstack, + pointed_thing) or itemstack + end + + local above = pointed_thing.above + local wdir = minetest.dir_to_wallmounted(vector.subtract(under, above)) + local fakestack = itemstack + if wdir == 0 then + fakestack:set_name("default:torch_ceiling") + elseif wdir == 1 then + fakestack:set_name("default:torch") + else + fakestack:set_name("default:torch_wall") + end + + itemstack = minetest.item_place(fakestack, placer, pointed_thing, wdir) + itemstack:set_name("default:torch") + + return itemstack + end, + floodable = true, + on_flood = on_flood, +}) + +minetest.register_node("default:torch_wall", { + drawtype = "mesh", + mesh = "torch_wall.obj", + tiles = {{ + name = "default_torch_on_floor_animated.png", + animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3} + }}, + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + 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 = { + type = "wallmounted", + wall_side = {-1/2, -1/2, -1/8, -1/8, 1/8, 1/8}, + }, + sounds = default.node_sound_wood_defaults(), + floodable = true, + on_flood = on_flood, +}) + +minetest.register_node("default:torch_ceiling", { + drawtype = "mesh", + mesh = "torch_ceiling.obj", + tiles = {{ + name = "default_torch_on_floor_animated.png", + animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3} + }}, + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + walkable = false, + 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 = { + type = "wallmounted", + wall_top = {-1/8, -1/16, -5/16, 1/8, 1/2, 1/8}, + }, + sounds = default.node_sound_wood_defaults(), + floodable = true, + on_flood = on_flood, +}) + +minetest.register_lbm({ + name = "default:3dtorch", + nodenames = {"default:torch", "torches:floor", "torches:wall"}, + action = function(pos, node) + if node.param2 == 0 then + minetest.set_node(pos, {name = "default:torch_ceiling", + param2 = node.param2}) + elseif node.param2 == 1 then + minetest.set_node(pos, {name = "default:torch", + param2 = node.param2}) + else + minetest.set_node(pos, {name = "default:torch_wall", + param2 = node.param2}) + end + end +}) diff --git a/mods/default/trees.lua b/mods/default/trees.lua new file mode 100644 index 0000000..c9eabaa --- /dev/null +++ b/mods/default/trees.lua @@ -0,0 +1,590 @@ +local random = math.random + +-- +-- Grow trees from saplings +-- + +-- 'can grow' function + +function default.can_grow(pos) + local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) + if not node_under then + return false + end + local name_under = node_under.name + local is_soil = minetest.get_item_group(name_under, "soil") + if is_soil == 0 then + return false + end + local light_level = minetest.get_node_light(pos) + if not light_level or light_level < 13 then + return false + end + return true +end + + +-- 'is snow nearby' function + +local function is_snow_nearby(pos) + return minetest.find_node_near(pos, 1, {"group:snowy"}) +end + + +-- Grow sapling + +function default.grow_sapling(pos) + if not default.can_grow(pos) then + -- try again 5 min later + minetest.get_node_timer(pos):start(300) + return + end + + local mg_name = minetest.get_mapgen_setting("mg_name") + local node = minetest.get_node(pos) + if node.name == "default:sapling" then + minetest.log("action", "A sapling grows into a tree at ".. + minetest.pos_to_string(pos)) + if mg_name == "v6" then + default.grow_tree(pos, random(1, 4) == 1) + else + default.grow_new_apple_tree(pos) + end + elseif node.name == "default:junglesapling" then + minetest.log("action", "A jungle sapling grows into a tree at ".. + minetest.pos_to_string(pos)) + if mg_name == "v6" then + default.grow_jungle_tree(pos) + else + default.grow_new_jungle_tree(pos) + end + elseif node.name == "default:pine_sapling" then + minetest.log("action", "A pine sapling grows into a tree at ".. + minetest.pos_to_string(pos)) + local snow = is_snow_nearby(pos) + if mg_name == "v6" then + default.grow_pine_tree(pos, snow) + elseif snow then + default.grow_new_snowy_pine_tree(pos) + else + default.grow_new_pine_tree(pos) + end + elseif node.name == "default:acacia_sapling" then + minetest.log("action", "An acacia sapling grows into a tree at ".. + minetest.pos_to_string(pos)) + default.grow_new_acacia_tree(pos) + elseif node.name == "default:aspen_sapling" then + 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:blueberry_bush_sapling" then + minetest.log("action", "A blueberry bush sapling grows into a bush at ".. + minetest.pos_to_string(pos)) + default.grow_blueberry_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) + elseif node.name == "default:pine_bush_sapling" then + minetest.log("action", "A pine bush sapling grows into a bush at ".. + minetest.pos_to_string(pos)) + default.grow_pine_bush(pos) + elseif node.name == "default:emergent_jungle_sapling" then + minetest.log("action", "An emergent jungle sapling grows into a tree at ".. + minetest.pos_to_string(pos)) + default.grow_new_emergent_jungle_tree(pos) + end +end + +minetest.register_lbm({ + name = "default:convert_saplings_to_node_timer", + nodenames = {"default:sapling", "default:junglesapling", + "default:pine_sapling", "default:acacia_sapling", + "default:aspen_sapling"}, + action = function(pos) + minetest.get_node_timer(pos):start(math.random(300, 1500)) + end +}) + +-- +-- Tree generation +-- + +-- Apple tree and jungle tree trunk and leaves function + +local function add_trunk_and_leaves(data, a, pos, tree_cid, leaves_cid, + height, size, iters, is_apple_tree) + local x, y, z = pos.x, pos.y, pos.z + local c_air = minetest.get_content_id("air") + local c_ignore = minetest.get_content_id("ignore") + local c_apple = minetest.get_content_id("default:apple") + + -- Trunk + data[a:index(x, y, z)] = tree_cid -- Force-place lowest trunk node to replace sapling + for yy = y + 1, y + height - 1 do + local vi = a:index(x, yy, z) + local node_id = data[vi] + if node_id == c_air or node_id == c_ignore or node_id == leaves_cid then + data[vi] = tree_cid + end + end + + -- Force leaves near the trunk + for z_dist = -1, 1 do + for y_dist = -size, 1 do + local vi = a:index(x - 1, y + height + y_dist, z + z_dist) + for x_dist = -1, 1 do + if data[vi] == c_air or data[vi] == c_ignore then + if is_apple_tree and random(1, 8) == 1 then + data[vi] = c_apple + else + data[vi] = leaves_cid + end + end + vi = vi + 1 + end + end + end + + -- Randomly add leaves in 2x2x2 clusters. + for i = 1, iters do + local clust_x = x + random(-size, size - 1) + local clust_y = y + height + random(-size, 0) + local clust_z = z + random(-size, size - 1) + + for xi = 0, 1 do + for yi = 0, 1 do + for zi = 0, 1 do + local vi = a:index(clust_x + xi, clust_y + yi, clust_z + zi) + if data[vi] == c_air or data[vi] == c_ignore then + if is_apple_tree and random(1, 8) == 1 then + data[vi] = c_apple + else + data[vi] = leaves_cid + end + end + end + end + end + end +end + + +-- Apple tree + +function default.grow_tree(pos, is_apple_tree, bad) + --[[ + NOTE: Tree-placing code is currently duplicated in the engine + and in games that have saplings; both are deprecated but not + replaced yet + --]] + if bad then + error("Deprecated use of default.grow_tree") + end + + local x, y, z = pos.x, pos.y, pos.z + local height = random(4, 5) + local c_tree = minetest.get_content_id("default:tree") + local c_leaves = minetest.get_content_id("default:leaves") + + local vm = minetest.get_voxel_manip() + local minp, maxp = vm:read_from_map( + {x = x - 2, y = y, z = z - 2}, + {x = x + 2, y = y + height + 1, z = z + 2} + ) + local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + local data = vm:get_data() + + add_trunk_and_leaves(data, a, pos, c_tree, c_leaves, height, 2, 8, is_apple_tree) + + vm:set_data(data) + vm:write_to_map() + vm:update_map() +end + + +-- Jungle tree + +function default.grow_jungle_tree(pos, bad) + --[[ + NOTE: Jungletree-placing code is currently duplicated in the engine + and in games that have saplings; both are deprecated but not + replaced yet + --]] + if bad then + error("Deprecated use of default.grow_jungle_tree") + end + + local x, y, z = pos.x, pos.y, pos.z + local height = random(8, 12) + local c_air = minetest.get_content_id("air") + local c_ignore = minetest.get_content_id("ignore") + local c_jungletree = minetest.get_content_id("default:jungletree") + local c_jungleleaves = minetest.get_content_id("default:jungleleaves") + + local vm = minetest.get_voxel_manip() + local minp, maxp = vm:read_from_map( + {x = x - 3, y = y - 1, z = z - 3}, + {x = x + 3, y = y + height + 1, z = z + 3} + ) + local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + local data = vm:get_data() + + add_trunk_and_leaves(data, a, pos, c_jungletree, c_jungleleaves, + height, 3, 30, false) + + -- Roots + for z_dist = -1, 1 do + local vi_1 = a:index(x - 1, y - 1, z + z_dist) + local vi_2 = a:index(x - 1, y, z + z_dist) + for x_dist = -1, 1 do + if random(1, 3) >= 2 then + if data[vi_1] == c_air or data[vi_1] == c_ignore then + data[vi_1] = c_jungletree + elseif data[vi_2] == c_air or data[vi_2] == c_ignore then + data[vi_2] = c_jungletree + end + end + vi_1 = vi_1 + 1 + vi_2 = vi_2 + 1 + end + end + + vm:set_data(data) + vm:write_to_map() + vm:update_map() +end + + +-- Pine tree from mg mapgen mod, design by sfan5, pointy top added by paramat + +local function add_pine_needles(data, vi, c_air, c_ignore, c_snow, c_pine_needles) + local node_id = data[vi] + if node_id == c_air or node_id == c_ignore or node_id == c_snow then + data[vi] = c_pine_needles + end +end + +local function add_snow(data, vi, c_air, c_ignore, c_snow) + local node_id = data[vi] + if node_id == c_air or node_id == c_ignore then + data[vi] = c_snow + end +end + +function default.grow_pine_tree(pos, snow) + local x, y, z = pos.x, pos.y, pos.z + local maxy = y + random(9, 13) -- Trunk top + + local c_air = minetest.get_content_id("air") + local c_ignore = minetest.get_content_id("ignore") + local c_pine_tree = minetest.get_content_id("default:pine_tree") + local c_pine_needles = minetest.get_content_id("default:pine_needles") + local c_snow = minetest.get_content_id("default:snow") + + local vm = minetest.get_voxel_manip() + local minp, maxp = vm:read_from_map( + {x = x - 3, y = y, z = z - 3}, + {x = x + 3, y = maxy + 3, z = z + 3} + ) + local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + local data = vm:get_data() + + -- Upper branches layer + local dev = 3 + for yy = maxy - 1, maxy + 1 do + for zz = z - dev, z + dev do + local vi = a:index(x - dev, yy, zz) + local via = a:index(x - dev, yy + 1, zz) + for xx = x - dev, x + dev do + if random() < 0.95 - dev * 0.05 then + add_pine_needles(data, vi, c_air, c_ignore, c_snow, + c_pine_needles) + if snow then + add_snow(data, via, c_air, c_ignore, c_snow) + end + end + vi = vi + 1 + via = via + 1 + end + end + dev = dev - 1 + end + + -- Centre top nodes + add_pine_needles(data, a:index(x, maxy + 1, z), c_air, c_ignore, c_snow, + c_pine_needles) + add_pine_needles(data, a:index(x, maxy + 2, z), c_air, c_ignore, c_snow, + c_pine_needles) -- Paramat added a pointy top node + if snow then + add_snow(data, a:index(x, maxy + 3, z), c_air, c_ignore, c_snow) + end + + -- Lower branches layer + local my = 0 + for i = 1, 20 do -- Random 2x2 squares of needles + local xi = x + random(-3, 2) + local yy = maxy + random(-6, -5) + local zi = z + random(-3, 2) + if yy > my then + my = yy + end + for zz = zi, zi+1 do + local vi = a:index(xi, yy, zz) + local via = a:index(xi, yy + 1, zz) + for xx = xi, xi + 1 do + add_pine_needles(data, vi, c_air, c_ignore, c_snow, + c_pine_needles) + if snow then + add_snow(data, via, c_air, c_ignore, c_snow) + end + vi = vi + 1 + via = via + 1 + end + end + end + + dev = 2 + for yy = my + 1, my + 2 do + for zz = z - dev, z + dev do + local vi = a:index(x - dev, yy, zz) + local via = a:index(x - dev, yy + 1, zz) + for xx = x - dev, x + dev do + if random() < 0.95 - dev * 0.05 then + add_pine_needles(data, vi, c_air, c_ignore, c_snow, + c_pine_needles) + if snow then + add_snow(data, via, c_air, c_ignore, c_snow) + end + end + vi = vi + 1 + via = via + 1 + end + end + dev = dev - 1 + end + + -- Trunk + -- Force-place lowest trunk node to replace sapling + data[a:index(x, y, z)] = c_pine_tree + for yy = y + 1, maxy do + local vi = a:index(x, yy, z) + local node_id = data[vi] + if node_id == c_air or node_id == c_ignore or + node_id == c_pine_needles or node_id == c_snow then + data[vi] = c_pine_tree + end + end + + vm:set_data(data) + vm:write_to_map() + vm:update_map() +end + + +-- New apple tree + +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 - 3, y = pos.y - 1, z = pos.z - 3}, + path, "random", nil, false) +end + + +-- New jungle tree + +function default.grow_new_jungle_tree(pos) + local path = minetest.get_modpath("default") .. + "/schematics/jungle_tree_from_sapling.mts" + minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, + path, "random", nil, false) +end + + +-- New emergent jungle tree + +function default.grow_new_emergent_jungle_tree(pos) + local path = minetest.get_modpath("default") .. + "/schematics/emergent_jungle_tree_from_sapling.mts" + minetest.place_schematic({x = pos.x - 3, y = pos.y - 5, z = pos.z - 3}, + path, "random", nil, false) +end + + +-- New pine tree + +function default.grow_new_pine_tree(pos) + local path + if math.random() > 0.5 then + path = minetest.get_modpath("default") .. + "/schematics/pine_tree_from_sapling.mts" + else + path = minetest.get_modpath("default") .. + "/schematics/small_pine_tree_from_sapling.mts" + end + minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, + path, "0", nil, false) +end + + +-- New snowy pine tree + +function default.grow_new_snowy_pine_tree(pos) + local path + if math.random() > 0.5 then + path = minetest.get_modpath("default") .. + "/schematics/snowy_pine_tree_from_sapling.mts" + else + path = minetest.get_modpath("default") .. + "/schematics/snowy_small_pine_tree_from_sapling.mts" + end + minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, + path, "random", nil, false) +end + + +-- New acacia tree + +function default.grow_new_acacia_tree(pos) + local path = minetest.get_modpath("default") .. + "/schematics/acacia_tree_from_sapling.mts" + minetest.place_schematic({x = pos.x - 4, y = pos.y - 1, z = pos.z - 4}, + path, "random", nil, false) +end + + +-- New aspen tree + +function default.grow_new_aspen_tree(pos) + local path = minetest.get_modpath("default") .. + "/schematics/aspen_tree_from_sapling.mts" + minetest.place_schematic({x = pos.x - 2, y = pos.y - 1, z = pos.z - 2}, + path, "0", nil, false) +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 + +-- Blueberry bush + +function default.grow_blueberry_bush(pos) + local path = minetest.get_modpath("default") .. + "/schematics/blueberry_bush.mts" + minetest.place_schematic({x = pos.x - 1, y = pos.y, 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 + + +-- Pine bush + +function default.grow_pine_bush(pos) + local path = minetest.get_modpath("default") .. + "/schematics/pine_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 +-- + +function default.sapling_on_place(itemstack, placer, pointed_thing, + sapling_name, minp_relative, maxp_relative, interval) + -- Position of sapling + local pos = pointed_thing.under + local node = minetest.get_node_or_nil(pos) + local pdef = node and minetest.registered_nodes[node.name] + + if pdef and pdef.on_rightclick and + not (placer and placer:is_player() and + placer:get_player_control().sneak) then + return pdef.on_rightclick(pos, node, placer, itemstack, pointed_thing) + end + + if not pdef or not pdef.buildable_to then + pos = pointed_thing.above + node = minetest.get_node_or_nil(pos) + pdef = node and minetest.registered_nodes[node.name] + if not pdef or not pdef.buildable_to then + return itemstack + end + end + + local player_name = placer and placer:get_player_name() or "" + -- Check sapling position for protection + if minetest.is_protected(pos, player_name) then + minetest.record_protection_violation(pos, player_name) + return itemstack + end + -- Check tree volume for protection + if minetest.is_area_protected( + vector.add(pos, minp_relative), + vector.add(pos, maxp_relative), + player_name, + interval) then + 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 +end diff --git a/mods/doors/README.txt b/mods/doors/README.txt new file mode 100644 index 0000000..ba8bd82 --- /dev/null +++ b/mods/doors/README.txt @@ -0,0 +1,85 @@ +Minetest Game mod: doors +======================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by PilzAdam (MIT) + +Modified by BlockMen (MIT): Added sounds, glass doors (glass, obsidian glass) and trapdoor. + +Modified by sofar (sofar@foo-projects.org) (MIT): +Added Steel trapdoor. +Re-implemented most of the door algorithms, added meshes, UV wrapped texture. +Added doors API to facilitate coding mods accessing and operating doors. +Added Fence Gate model, code, and sounds. + +Various Minetest developers and contributors (MIT) + + +Authors of media (textures) +--------------------------- +Following textures created by Fernando Zapata (CC BY-SA 3.0): + door_wood.png + door_wood_a.png + door_wood_a_r.png + door_wood_b.png + door_wood_b_r.png + +Following textures created by BlockMen (CC BY-SA 3.0): + door_trapdoor.png + door_obsidian_glass_side.png + +Following textures created by celeron55 (CC BY-SA 3.0): + door_glass_a.png + door_glass_b.png + +Following textures created by PenguinDad (CC BY-SA 4.0): + door_glass.png + door_obsidian_glass.png + +Following textures created by sofar (CC-BY-SA-3.0): + doors_trapdoor_steel.png + doors_trapdoor_steel_side.png + door_trapdoor_side.png + +Obsidian door textures by red-001 based on textures by Pilzadam and BlockMen (CC BY-SA 3.0): + door_obsidian_glass.png + +Glass door textures by Krock based on textures by VanessaE (CC BY-SA 3.0): + doors_door_glass.png + doors_item_glass.png + +All other textures (created by PilzAdam) (CC BY-SA 3.0): + +Door textures were converted to the new texture map by sofar, paramat and +red-001, under the same license as the originals. + + +Authors of media (models) +------------------------- +Door 3d models by sofar (CC-BY-SA-3.0) + - door_a.obj + - door_b.obj +Fence gate models by sofar (CC-BY-SA-3.0) + - fencegate_open.obj + - fencegate_closed.obj + + +Authors of media (sounds) +------------------------- +Opening-Sound created by CGEffex (CC BY 3.0), modified by BlockMen + door_open.ogg +Closing-Sound created by bennstir (CC BY 3.0) + door_close.ogg +fencegate_open.ogg: + http://www.freesound.org/people/mhtaylor67/sounds/126041/ - (CC0 1.0) +fencegate_close.ogg: + http://www.freesound.org/people/BarkersPinhead/sounds/274807/ - (CC-BY-3.0) + http://www.freesound.org/people/rivernile7/sounds/249573/ - (CC-BY-3.0) +Steel door sounds open & close (CC-BY-3.0) by HazMatt + - http://www.freesound.org/people/HazMattt/sounds/187283/ + doors_steel_door_open.ogg + doors_steel_door_close.ogg +doors_glass_door_open.ogg, doors_glass_door_close.ogg: + https://www.freesound.org/people/SkeetMasterFunk69/sounds/235546/ (CC0 1.0) diff --git a/mods/doors/depends.txt b/mods/doors/depends.txt new file mode 100644 index 0000000..5e28bee --- /dev/null +++ b/mods/doors/depends.txt @@ -0,0 +1,2 @@ +default +screwdriver? diff --git a/mods/doors/init.lua b/mods/doors/init.lua new file mode 100644 index 0000000..2685357 --- /dev/null +++ b/mods/doors/init.lua @@ -0,0 +1,861 @@ +-- our API object +doors = {} + +-- private data +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 + if _doors.registered_doors[node_name] then + -- A normal upright door + return { + pos = pos, + open = function(self, player) + if self:state() then + return false + end + return _doors.door_toggle(self.pos, nil, player) + end, + close = function(self, player) + if not self:state() then + return false + end + return _doors.door_toggle(self.pos, nil, player) + end, + toggle = function(self, player) + return _doors.door_toggle(self.pos, nil, player) + end, + state = function(self) + local state = minetest.get_meta(self.pos):get_int("state") + return state %2 == 1 + end + } + elseif _doors.registered_trapdoors[node_name] then + -- A trapdoor + return { + pos = pos, + open = function(self, player) + if self:state() then + return false + end + return _doors.trapdoor_toggle(self.pos, nil, player) + end, + close = function(self, player) + if not self:state() then + return false + end + return _doors.trapdoor_toggle(self.pos, nil, player) + end, + toggle = function(self, player) + return _doors.trapdoor_toggle(self.pos, nil, player) + end, + state = function(self) + return minetest.get_node(self.pos).name:sub(-5) == "_open" + end + } + else + return nil + end +end + +-- this hidden node is placed on top of the bottom, and prevents +-- nodes from being placed in the top half of the door. +minetest.register_node("doors:hidden", { + description = "Hidden Door Segment", + -- can't use airlike otherwise falling nodes will turn to entities + -- and will be forever stuck until door is removed. + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + -- has to be walkable for falling nodes to stop falling. + walkable = true, + pointable = false, + diggable = false, + buildable_to = false, + floodable = false, + drop = "", + groups = {not_in_creative_inventory = 1}, + on_blast = function() end, + tiles = {"doors_blank.png"}, + -- 1px transparent block inside door hinge near node top. + node_box = { + type = "fixed", + fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32}, + }, + -- collision_box needed otherise selection box would be full node size + collision_box = { + type = "fixed", + fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32}, + }, +}) + +-- table used to aid door opening/closing +local transform = { + { + {v = "_a", param2 = 3}, + {v = "_a", param2 = 0}, + {v = "_a", param2 = 1}, + {v = "_a", param2 = 2}, + }, + { + {v = "_b", param2 = 1}, + {v = "_b", param2 = 2}, + {v = "_b", param2 = 3}, + {v = "_b", param2 = 0}, + }, + { + {v = "_b", param2 = 1}, + {v = "_b", param2 = 2}, + {v = "_b", param2 = 3}, + {v = "_b", param2 = 0}, + }, + { + {v = "_a", param2 = 3}, + {v = "_a", param2 = 0}, + {v = "_a", param2 = 1}, + {v = "_a", param2 = 2}, + }, +} + +function _doors.door_toggle(pos, node, clicker) + local meta = minetest.get_meta(pos) + node = node or minetest.get_node(pos) + local def = minetest.registered_nodes[node.name] + local name = def.door.name + + local state = meta:get_string("state") + if state == "" then + -- fix up lvm-placed right-hinged doors, default closed + if node.name:sub(-2) == "_b" then + state = 2 + else + state = 0 + end + else + state = tonumber(state) + end + + replace_old_owner_information(pos) + + if clicker and not default.can_interact_with_node(clicker, pos) then + return false + end + + -- until Lua-5.2 we have no bitwise operators :( + if state % 2 == 1 then + state = state - 1 + else + state = state + 1 + end + + local dir = node.param2 + if state % 2 == 0 then + minetest.sound_play(def.door.sounds[1], + {pos = pos, gain = 0.3, max_hear_distance = 10}) + else + minetest.sound_play(def.door.sounds[2], + {pos = pos, gain = 0.3, max_hear_distance = 10}) + end + + minetest.swap_node(pos, { + name = name .. transform[state + 1][dir+1].v, + param2 = transform[state + 1][dir+1].param2 + }) + meta:set_int("state", state) + + return true +end + + +local function on_place_node(place_to, newnode, + placer, oldnode, itemstack, pointed_thing) + -- Run script hook + for _, callback in ipairs(minetest.registered_on_placenodes) do + -- Deepcopy pos, node and pointed_thing because callback can modify them + local place_to_copy = {x = place_to.x, y = place_to.y, z = place_to.z} + local newnode_copy = + {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2} + local oldnode_copy = + {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2} + local pointed_thing_copy = { + type = pointed_thing.type, + above = vector.new(pointed_thing.above), + under = vector.new(pointed_thing.under), + ref = pointed_thing.ref, + } + callback(place_to_copy, newnode_copy, placer, + oldnode_copy, itemstack, pointed_thing_copy) + end +end + +local function can_dig_door(pos, digger) + replace_old_owner_information(pos) + return default.can_interact_with_node(digger, pos) +end + +function doors.register(name, def) + if not name:find(":") then + name = "doors:" .. name + end + + -- replace old doors of this type automatically + minetest.register_lbm({ + name = ":doors:replace_" .. name:gsub(":", "_"), + nodenames = {name.."_b_1", name.."_b_2"}, + action = function(pos, node) + local l = tonumber(node.name:sub(-1)) + local meta = minetest.get_meta(pos) + local h = meta:get_int("right") + 1 + local p2 = node.param2 + local replace = { + {{type = "a", state = 0}, {type = "a", state = 3}}, + {{type = "b", state = 1}, {type = "b", state = 2}} + } + local new = replace[l][h] + -- retain infotext and doors_owner fields + minetest.swap_node(pos, {name = name .. "_" .. new.type, param2 = p2}) + meta:set_int("state", new.state) + -- properly place doors:hidden at the right spot + local p3 = p2 + if new.state >= 2 then + p3 = (p3 + 3) % 4 + end + if new.state % 2 == 1 then + if new.state >= 2 then + p3 = (p3 + 1) % 4 + else + p3 = (p3 + 3) % 4 + end + end + -- wipe meta on top node as it's unused + minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, + {name = "doors:hidden", param2 = p3}) + end + }) + + 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 + + if not pointed_thing.type == "node" then + return itemstack + end + + local node = minetest.get_node(pointed_thing.under) + local pdef = minetest.registered_nodes[node.name] + if pdef and pdef.on_rightclick and + not (placer and placer:is_player() and + placer:get_player_control().sneak) then + return pdef.on_rightclick(pointed_thing.under, + node, placer, itemstack, pointed_thing) + end + + if pdef and pdef.buildable_to then + pos = pointed_thing.under + else + pos = pointed_thing.above + node = minetest.get_node(pos) + pdef = minetest.registered_nodes[node.name] + if not pdef or not pdef.buildable_to then + return itemstack + end + end + + local above = {x = pos.x, y = pos.y + 1, z = pos.z} + local top_node = minetest.get_node_or_nil(above) + local topdef = top_node and minetest.registered_nodes[top_node.name] + + if not topdef or not topdef.buildable_to then + return itemstack + end + + local pn = placer and placer:get_player_name() or "" + if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then + return itemstack + end + + local dir = placer and minetest.dir_to_facedir(placer:get_look_dir()) or 0 + + local ref = { + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 1, y = 0, z = 0}, + {x = 0, y = 0, z = -1}, + } + + local aside = { + x = pos.x + ref[dir + 1].x, + y = pos.y + ref[dir + 1].y, + z = pos.z + ref[dir + 1].z, + } + + local state = 0 + if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then + state = state + 2 + minetest.set_node(pos, {name = name .. "_b", param2 = dir}) + minetest.set_node(above, {name = "doors:hidden", param2 = (dir + 3) % 4}) + else + minetest.set_node(pos, {name = name .. "_a", param2 = dir}) + minetest.set_node(above, {name = "doors:hidden", param2 = dir}) + end + + local meta = minetest.get_meta(pos) + meta:set_int("state", state) + + if def.protected then + meta:set_string("owner", pn) + meta:set_string("infotext", "Owned by " .. pn) + end + + 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) + + return itemstack + end + }) + def.inventory_image = nil + + if def.recipe then + minetest.register_craft({ + output = name, + recipe = def.recipe, + }) + end + def.recipe = nil + + if not def.sounds then + def.sounds = default.node_sound_wood_defaults() + end + + if not def.sound_open then + def.sound_open = "doors_door_open" + end + + if not def.sound_close then + def.sound_close = "doors_door_close" + end + + def.groups.not_in_creative_inventory = 1 + def.groups.door = 1 + def.drop = name + def.door = { + name = name, + sounds = { def.sound_close, def.sound_open }, + } + + def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + _doors.door_toggle(pos, node, clicker) + return itemstack + end + def.after_dig_node = function(pos, node, meta, digger) + 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 = function(pos, node, user, mode, new_param2) + return false + end + + if def.protected then + def.can_dig = can_dig_door + def.on_blast = function() end + def.on_key_use = function(pos, player) + local door = doors.get(pos) + 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("owner") + local pname = player:get_player_name() + + -- verify placer is owner of lockable door + if owner ~= pname then + minetest.record_protection_violation(pos, pname) + minetest.chat_send_player(pname, "You do not own this locked door.") + 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 door", owner + end + def.node_dig_prediction = "" + else + def.on_blast = function(pos, intensity) + minetest.remove_node(pos) + -- hidden node doesn't get blasted away. + minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) + return {name} + end + end + + def.on_destruct = function(pos) + minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) + end + + def.drawtype = "mesh" + def.paramtype = "light" + def.paramtype2 = "facedir" + def.sunlight_propagates = true + def.walkable = true + def.is_ground_content = false + def.buildable_to = false + def.selection_box = {type = "fixed", fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}} + def.collision_box = {type = "fixed", fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}} + + def.mesh = "door_a.obj" + minetest.register_node(":" .. name .. "_a", def) + + def.mesh = "door_b.obj" + minetest.register_node(":" .. name .. "_b", def) + + _doors.registered_doors[name .. "_a"] = true + _doors.registered_doors[name .. "_b"] = true +end + +doors.register("door_wood", { + tiles = {{ name = "doors_door_wood.png", backface_culling = true }}, + description = "Wooden Door", + inventory_image = "doors_item_wood.png", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + recipe = { + {"group:wood", "group:wood"}, + {"group:wood", "group:wood"}, + {"group:wood", "group:wood"}, + } +}) + +doors.register("door_steel", { + tiles = {{name = "doors_door_steel.png", backface_culling = true}}, + description = "Steel Door", + inventory_image = "doors_item_steel.png", + protected = true, + groups = {cracky = 1, level = 2}, + sounds = default.node_sound_metal_defaults(), + sound_open = "doors_steel_door_open", + sound_close = "doors_steel_door_close", + recipe = { + {"default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot"}, + } +}) + +doors.register("door_glass", { + tiles = {"doors_door_glass.png"}, + description = "Glass Door", + inventory_image = "doors_item_glass.png", + groups = {cracky=3, oddly_breakable_by_hand=3}, + sounds = default.node_sound_glass_defaults(), + sound_open = "doors_glass_door_open", + sound_close = "doors_glass_door_close", + recipe = { + {"default:glass", "default:glass"}, + {"default:glass", "default:glass"}, + {"default:glass", "default:glass"}, + } +}) + +doors.register("door_obsidian_glass", { + tiles = {"doors_door_obsidian_glass.png"}, + description = "Obsidian Glass Door", + inventory_image = "doors_item_obsidian_glass.png", + groups = {cracky=3}, + sounds = default.node_sound_glass_defaults(), + sound_open = "doors_glass_door_open", + sound_close = "doors_glass_door_close", + recipe = { + {"default:obsidian_glass", "default:obsidian_glass"}, + {"default:obsidian_glass", "default:obsidian_glass"}, + {"default:obsidian_glass", "default:obsidian_glass"}, + }, +}) + +-- Capture mods using the old API as best as possible. +function doors.register_door(name, def) + if def.only_placer_can_open then + def.protected = true + end + def.only_placer_can_open = nil + + local i = name:find(":") + local modname = name:sub(1, i - 1) + if not def.tiles then + if def.protected then + def.tiles = {{name = "doors_door_steel.png", backface_culling = true}} + else + def.tiles = {{name = "doors_door_wood.png", backface_culling = true}} + end + minetest.log("warning", modname .. " registered door \"" .. name .. "\" " .. + "using deprecated API method \"doors.register_door()\" but " .. + "did not provide the \"tiles\" parameter. A fallback tiledef " .. + "will be used instead.") + end + + doors.register(name, def) +end + +----trapdoor---- + +function _doors.trapdoor_toggle(pos, node, clicker) + node = node or minetest.get_node(pos) + + 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] + + if string.sub(node.name, -5) == "_open" then + minetest.sound_play(def.sound_close, + {pos = pos, gain = 0.3, max_hear_distance = 10}) + minetest.swap_node(pos, {name = string.sub(node.name, 1, + string.len(node.name) - 5), param1 = node.param1, param2 = node.param2}) + else + minetest.sound_play(def.sound_open, + {pos = pos, gain = 0.3, max_hear_distance = 10}) + minetest.swap_node(pos, {name = node.name .. "_open", + param1 = node.param1, param2 = node.param2}) + end +end + +function doors.register_trapdoor(name, def) + if not name:find(":") then + name = "doors:" .. name + end + + local name_closed = name + local name_opened = name.."_open" + + def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + _doors.trapdoor_toggle(pos, node, clicker) + return itemstack + end + + -- Common trapdoor configuration + def.drawtype = "nodebox" + def.paramtype = "light" + def.paramtype2 = "facedir" + def.is_ground_content = false + + if def.protected then + def.can_dig = can_dig_door + 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("owner", pn) + meta:set_string("infotext", "Owned by "..pn) + + return (creative and creative.is_enabled_for and creative.is_enabled_for(pn)) + end + + def.on_blast = function() end + def.on_key_use = function(pos, player) + local door = doors.get(pos) + 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("owner") + local pname = player:get_player_name() + + -- verify placer is owner of lockable door + if owner ~= pname then + minetest.record_protection_violation(pos, pname) + minetest.chat_send_player(pname, "You do not own this trapdoor.") + 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 trapdoor", owner + end + def.node_dig_prediction = "" + else + def.on_blast = function(pos, intensity) + minetest.remove_node(pos) + return {name} + end + end + + if not def.sounds then + def.sounds = default.node_sound_wood_defaults() + end + + if not def.sound_open then + def.sound_open = "doors_door_open" + end + + if not def.sound_close then + def.sound_close = "doors_door_close" + end + + local def_opened = table.copy(def) + local def_closed = table.copy(def) + + def_closed.node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} + } + def_closed.selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} + } + def_closed.tiles = {def.tile_front, + def.tile_front .. '^[transformFY', + def.tile_side, def.tile_side, + def.tile_side, def.tile_side} + + def_opened.node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} + } + def_opened.selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} + } + def_opened.tiles = {def.tile_side, def.tile_side, + def.tile_side .. '^[transform3', + def.tile_side .. '^[transform1', + def.tile_front .. '^[transform46', + def.tile_front .. '^[transform6'} + + def_opened.drop = name_closed + def_opened.groups.not_in_creative_inventory = 1 + + minetest.register_node(name_opened, def_opened) + minetest.register_node(name_closed, def_closed) + + _doors.registered_trapdoors[name_opened] = true + _doors.registered_trapdoors[name_closed] = true +end + +doors.register_trapdoor("doors:trapdoor", { + description = "Wooden Trapdoor", + inventory_image = "doors_trapdoor.png", + wield_image = "doors_trapdoor.png", + tile_front = "doors_trapdoor.png", + tile_side = "doors_trapdoor_side.png", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, door = 1}, +}) + +doors.register_trapdoor("doors:trapdoor_steel", { + description = "Steel Trapdoor", + inventory_image = "doors_trapdoor_steel.png", + wield_image = "doors_trapdoor_steel.png", + tile_front = "doors_trapdoor_steel.png", + tile_side = "doors_trapdoor_steel_side.png", + protected = true, + sounds = default.node_sound_metal_defaults(), + sound_open = "doors_steel_door_open", + sound_close = "doors_steel_door_close", + groups = {cracky = 1, level = 2, door = 1}, +}) + +minetest.register_craft({ + output = 'doors:trapdoor 2', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + {'', '', ''}, + } +}) + +minetest.register_craft({ + output = 'doors:trapdoor_steel', + recipe = { + {'default:steel_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot'}, + } +}) + + +----fence gate---- + +function doors.register_fencegate(name, def) + local fence = { + description = def.description, + drawtype = "mesh", + tiles = {}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + drop = name .. "_closed", + connect_sides = {"left", "right"}, + groups = def.groups, + sounds = def.sounds, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local node_def = minetest.registered_nodes[node.name] + minetest.swap_node(pos, {name = node_def.gate, param2 = node.param2}) + minetest.sound_play(node_def.sound, {pos = pos, gain = 0.3, + max_hear_distance = 8}) + return itemstack + end, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/4, 1/2, 1/2, 1/4}, + }, + } + + + if type(def.texture) == "string" then + fence.tiles[1] = {name = def.texture, backface_culling = true} + elseif def.texture.backface_culling == nil then + fence.tiles[1] = table.copy(def.texture) + fence.tiles[1].backface_culling = true + else + fence.tiles[1] = def.texture + end + + if not fence.sounds then + fence.sounds = default.node_sound_wood_defaults() + end + + fence.groups.fence = 1 + + local fence_closed = table.copy(fence) + fence_closed.mesh = "doors_fencegate_closed.obj" + fence_closed.gate = name .. "_open" + fence_closed.sound = "doors_fencegate_open" + fence_closed.collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/4, 1/2, 1/2, 1/4}, + } + + local fence_open = table.copy(fence) + fence_open.mesh = "doors_fencegate_open.obj" + fence_open.gate = name .. "_closed" + fence_open.sound = "doors_fencegate_close" + fence_open.groups.not_in_creative_inventory = 1 + fence_open.collision_box = { + type = "fixed", + fixed = {{-1/2, -1/2, -1/4, -3/8, 1/2, 1/4}, + {-1/2, -3/8, -1/2, -3/8, 3/8, 0}}, + } + + minetest.register_node(":" .. name .. "_closed", fence_closed) + minetest.register_node(":" .. name .. "_open", fence_open) + + minetest.register_craft({ + output = name .. "_closed", + recipe = { + {"default:stick", def.material, "default:stick"}, + {"default:stick", def.material, "default:stick"} + } + }) +end + +doors.register_fencegate("doors:gate_wood", { + description = "Apple Wood Fence Gate", + texture = "default_wood.png", + material = "default:wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} +}) + +doors.register_fencegate("doors:gate_acacia_wood", { + description = "Acacia Wood Fence Gate", + texture = "default_acacia_wood.png", + material = "default:acacia_wood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} +}) + +doors.register_fencegate("doors:gate_junglewood", { + description = "Jungle Wood Fence Gate", + texture = "default_junglewood.png", + material = "default:junglewood", + groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} +}) + +doors.register_fencegate("doors:gate_pine_wood", { + description = "Pine Wood Fence Gate", + texture = "default_pine_wood.png", + material = "default:pine_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} +}) + +doors.register_fencegate("doors:gate_aspen_wood", { + description = "Aspen Wood Fence Gate", + texture = "default_aspen_wood.png", + material = "default:aspen_wood", + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} +}) + + +----fuels---- + +minetest.register_craft({ + type = "fuel", + recipe = "doors:trapdoor", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:door_wood", + burntime = 14, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:gate_wood_closed", + burntime = 7, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:gate_acacia_wood_closed", + burntime = 8, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:gate_junglewood_closed", + burntime = 9, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:gate_pine_wood_closed", + burntime = 6, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "doors:gate_aspen_wood_closed", + burntime = 5, +}) diff --git a/mods/doors/license.txt b/mods/doors/license.txt new file mode 100644 index 0000000..8ce73c4 --- /dev/null +++ b/mods/doors/license.txt @@ -0,0 +1,164 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2015-2016 sofar (sofar@foo-projects.org) +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures, models and sounds) +----------------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2011-2016 Fernando Zapata +Copyright (C) 2014-2016 celeron55 +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2015-2016 sofar +Copyright (C) 2016 red-001 +Copyright (C) 2016 paramat + +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/ + +----------------------- + +Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) +Copyright (C) 2014-2016 PenguinDad + +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/4.0/ + +----------------------- + +Attribution 3.0 Unported (CC BY 3.0) +Copyright (C) 2014 CGEffex +Copyright (C) 2014 bennstir +Copyright (C) 2016 BarkersPinhead +Copyright (C) 2016 rivernile7 +Copyright (C) 2016 HazMatt + +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. + +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/3.0/ + +----------------------- + +CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +mhtaylor67 +SkeetMasterFunk69 + +No Copyright + +The person who associated a work with this deed has dedicated the work to the public +domain by waiving all of his or her rights to the work worldwide under copyright law, +including all related and neighboring rights, to the extent allowed by law. + +You can copy, modify, distribute and perform the work, even for commercial purposes, all +without asking permission. See Other Information below. + +Other Information + +In no way are the patent or trademark rights of any person affected by CC0, nor are the +rights that other persons may have in the work or in how the work is used, such as +publicity or privacy rights. +Unless expressly stated otherwise, the person who associated a work with this deed makes +no warranties about the work, and disclaims liability for all uses of the work, to the +fullest extent permitted by applicable law. +When using or citing the work, you should not imply endorsement by the author or the +affirmer. + +For more details: +https://creativecommons.org/publicdomain/zero/1.0/ diff --git a/mods/doors/models/door_a.obj b/mods/doors/models/door_a.obj new file mode 100644 index 0000000..bd5127b --- /dev/null +++ b/mods/doors/models/door_a.obj @@ -0,0 +1,40 @@ +# Blender v2.76 (sub 0) OBJ File: 'door_a.blend' +# www.blender.org +mtllib door_a.mtl +o Cube_Cube.001 +v 0.499000 -0.499000 -0.499000 +v 0.499000 1.499000 -0.499000 +v 0.499000 -0.499000 -0.375000 +v 0.499000 1.499000 -0.375000 +v -0.499000 -0.499000 -0.499000 +v -0.499000 1.499000 -0.499000 +v -0.499000 -0.499000 -0.375000 +v -0.499000 1.499000 -0.375000 +vt 0.842105 1.000000 +vt 0.894737 1.000000 +vt 0.894737 0.000000 +vt 0.842105 0.000000 +vt 0.421053 1.000000 +vt 0.421053 0.000000 +vt 0.947368 1.000000 +vt 0.947368 0.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.500000 +vt 0.947368 0.500000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 2/1/1 4/2/1 3/3/1 1/4/1 +f 4/5/2 8/1/2 7/4/2 3/6/2 +f 8/2/3 6/7/3 5/8/3 7/3/3 +f 6/9/4 2/5/4 1/6/4 5/10/4 +f 1/11/5 3/12/5 7/7/5 5/13/5 +f 6/14/6 8/8/6 4/12/6 2/11/6 diff --git a/mods/doors/models/door_b.obj b/mods/doors/models/door_b.obj new file mode 100644 index 0000000..c5607b8 --- /dev/null +++ b/mods/doors/models/door_b.obj @@ -0,0 +1,40 @@ +# Blender v2.76 (sub 0) OBJ File: 'door_b.blend' +# www.blender.org +mtllib door_b.mtl +o Cube_Cube.001 +v -0.499000 -0.499000 -0.499000 +v -0.499000 1.499000 -0.499000 +v -0.499000 -0.499000 -0.375000 +v -0.499000 1.499000 -0.375000 +v 0.499000 -0.499000 -0.499000 +v 0.499000 1.499000 -0.499000 +v 0.499000 -0.499000 -0.375000 +v 0.499000 1.499000 -0.375000 +vt 0.842105 1.000000 +vt 0.842105 0.000000 +vt 0.894737 0.000000 +vt 0.894737 1.000000 +vt 0.421053 1.000000 +vt 0.421053 0.000000 +vt 0.947368 0.000000 +vt 0.947368 1.000000 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 0.500000 +vt 0.947368 0.500000 +vt 1.000000 1.000000 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +usemtl None +s off +f 2/1/1 1/2/1 3/3/1 4/4/1 +f 4/5/2 3/6/2 7/2/2 8/1/2 +f 8/4/3 7/3/3 5/7/3 6/8/3 +f 6/9/4 5/10/4 1/6/4 2/5/4 +f 1/11/5 5/12/5 7/13/5 3/7/5 +f 6/8/6 2/13/6 4/12/6 8/14/6 diff --git a/mods/doors/models/doors_fencegate_closed.obj b/mods/doors/models/doors_fencegate_closed.obj new file mode 100644 index 0000000..0050f70 --- /dev/null +++ b/mods/doors/models/doors_fencegate_closed.obj @@ -0,0 +1,106 @@ +# Blender v2.76 (sub 0) OBJ File: 'gate_closed.blend' +# www.blender.org +mtllib gate_closed.mtl +o Cube_Cube.001 +v -0.625000 -0.500000 0.125000 +v -0.625000 0.500100 0.125000 +v -0.625000 -0.500000 -0.125000 +v -0.625000 0.500100 -0.125000 +v -0.375000 -0.500000 0.125000 +v -0.375000 0.500100 0.125000 +v -0.375000 -0.500000 -0.125000 +v -0.375000 0.500100 -0.125000 +v 0.375000 -0.500000 0.125000 +v 0.375000 0.500100 0.125000 +v 0.375000 -0.500000 -0.125000 +v 0.375000 0.500100 -0.125000 +v 0.625000 -0.500000 0.125000 +v 0.625000 0.500100 0.125000 +v 0.625000 -0.500000 -0.125000 +v 0.625000 0.500100 -0.125000 +v -0.375000 0.187500 0.062500 +v -0.375000 0.312500 0.062500 +v -0.375000 0.187500 -0.062500 +v -0.375000 0.312500 -0.062500 +v 0.375000 0.187500 0.062500 +v 0.375000 0.312500 0.062500 +v 0.375000 0.187500 -0.062500 +v 0.375000 0.312500 -0.062500 +v -0.374831 0.187348 0.062500 +v -0.156342 0.187363 0.062500 +v -0.374831 0.187348 -0.062500 +v -0.156342 0.187363 -0.062500 +v 0.374981 -0.343683 0.062500 +v 0.375065 -0.187304 0.062500 +v 0.374981 -0.343683 -0.062500 +v 0.375065 -0.187304 -0.062500 +vt 0.000000 0.750000 +vt 0.000000 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.750000 +vt 1.000000 1.000000 +vt -0.000000 1.000000 +vt 1.000000 -0.000000 +vt 1.000000 0.250000 +vt 0.000000 0.250000 +vt -0.000000 0.000000 +vt 0.250000 0.000000 +vt 0.250000 0.250000 +vt 0.250000 0.750000 +vt 0.250000 1.000000 +vt 0.500000 -0.000000 +vt 0.500000 0.250000 +vt 0.500000 0.750000 +vt 0.500000 1.000000 +vt 1.000000 0.625000 +vt 0.000000 0.625000 +vt 1.000000 0.875000 +vt 0.000000 0.875000 +vt -0.000000 0.687500 +vt 0.000000 0.562500 +vt 1.000000 0.562500 +vt 1.000000 0.687500 +vt 0.813740 0.249033 +vt 0.201557 0.249293 +vt 0.120995 0.125498 +vt 0.987404 0.125469 +vt 0.125000 0.375000 +vt 0.812500 0.375000 +vt 0.937500 0.500000 +vt 0.062500 0.500000 +vt 0.000000 0.125000 +vt 1.000000 0.125000 +vt 0.312500 0.437500 +vt 0.312500 0.312500 +vt 1.000000 0.312500 +vt 1.000000 0.437500 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn -0.578000 -0.816100 0.000000 +vn 0.576200 0.817300 0.000000 +usemtl None +s off +f 2/1/1 4/2/1 3/3/1 1/4/1 +f 4/4/2 8/5/2 7/6/2 3/1/2 +f 8/7/3 6/8/3 5/9/3 7/10/3 +f 6/2/4 2/9/4 1/8/4 5/3/4 +f 1/9/5 3/10/5 7/11/5 5/12/5 +f 6/6/6 8/1/6 4/13/6 2/14/6 +f 10/1/1 12/2/1 11/3/1 9/4/1 +f 12/2/2 16/9/2 15/8/2 11/3/2 +f 16/7/3 14/8/3 13/9/3 15/10/3 +f 14/4/4 10/5/4 9/6/4 13/1/4 +f 9/12/5 11/11/5 15/15/5 13/16/5 +f 14/14/6 16/13/6 12/17/6 10/18/6 +f 20/2/2 24/3/2 23/19/2 19/20/2 +f 22/1/4 18/4/4 17/21/4 21/22/4 +f 17/23/5 19/24/5 23/25/5 21/26/5 +f 22/21/6 24/5/6 20/6/6 18/22/6 +f 28/27/2 32/28/2 31/29/2 27/30/2 +f 30/31/4 26/32/4 25/33/4 29/34/4 +f 25/35/7 27/10/7 31/7/7 29/36/7 +f 30/37/8 32/38/8 28/39/8 26/40/8 diff --git a/mods/doors/models/doors_fencegate_open.obj b/mods/doors/models/doors_fencegate_open.obj new file mode 100644 index 0000000..3fb727f --- /dev/null +++ b/mods/doors/models/doors_fencegate_open.obj @@ -0,0 +1,112 @@ +# Blender v2.76 (sub 0) OBJ File: 'gate_open.blend' +# www.blender.org +mtllib gate_open.mtl +o Cube_Cube.001 +v -0.625000 -0.500000 0.125000 +v -0.625000 0.500100 0.125000 +v -0.625000 -0.500000 -0.125000 +v -0.625000 0.500100 -0.125000 +v -0.375000 -0.500000 0.125000 +v -0.375000 0.500100 0.125000 +v -0.375000 -0.500000 -0.125000 +v -0.375000 0.500100 -0.125000 +v 0.375000 -0.500000 0.125000 +v 0.375000 0.500100 0.125000 +v 0.375000 -0.500000 -0.125000 +v 0.375000 0.500100 -0.125000 +v 0.625000 -0.500000 0.125000 +v 0.625000 0.500100 0.125000 +v 0.625000 -0.500000 -0.125000 +v 0.625000 0.500100 -0.125000 +v 0.434859 0.187500 -0.872359 +v 0.434859 0.312500 -0.872359 +v 0.559859 0.187500 -0.872359 +v 0.559859 0.312500 -0.872359 +v 0.434859 0.187500 -0.122359 +v 0.434859 0.312500 -0.122359 +v 0.559859 0.187500 -0.122359 +v 0.559859 0.312500 -0.122359 +v 0.434859 0.187348 -0.872190 +v 0.434859 0.187363 -0.653701 +v 0.559859 0.187348 -0.872190 +v 0.559859 0.187363 -0.653701 +v 0.434859 -0.343683 -0.122379 +v 0.434859 -0.187304 -0.122294 +v 0.559859 -0.343683 -0.122379 +v 0.559859 -0.187304 -0.122294 +v 0.499560 -0.442900 0.005495 +vt 0.000000 0.750000 +vt 0.000000 0.500000 +vt 1.000000 0.500000 +vt 1.000000 0.750000 +vt 1.000000 1.000000 +vt -0.000000 1.000000 +vt 1.000000 -0.000000 +vt 1.000000 0.250000 +vt 0.000000 0.250000 +vt -0.000000 0.000000 +vt 0.250000 0.000000 +vt 0.250000 0.250000 +vt 0.250000 0.750000 +vt 0.250000 1.000000 +vt 0.500000 -0.000000 +vt 0.500000 0.250000 +vt 0.500000 0.750000 +vt 0.500000 1.000000 +vt 1.000000 0.625000 +vt 0.000000 0.625000 +vt 1.000000 0.875000 +vt 0.000000 0.875000 +vt -0.000000 0.687500 +vt 0.000000 0.562500 +vt 1.000000 0.562500 +vt 1.000000 0.687500 +vt 0.813740 0.249033 +vt 0.201557 0.249293 +vt 0.120995 0.125498 +vt 0.987404 0.125469 +vt 0.125000 0.375000 +vt 0.812500 0.375000 +vt 0.937500 0.500000 +vt 0.062500 0.500000 +vt 0.000000 0.125000 +vt 1.000000 0.125000 +vt 0.312500 0.437500 +vt 0.312500 0.312500 +vt 1.000000 0.312500 +vt 1.000000 0.437500 +vt 0.312500 0.625000 +vt 0.312500 0.500000 +vt 0.187500 0.500000 +vt 0.187500 0.625000 +vn -1.000000 0.000000 0.000000 +vn 0.000000 0.000000 -1.000000 +vn 1.000000 0.000000 0.000000 +vn 0.000000 0.000000 1.000000 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 -0.816100 -0.578000 +vn 0.000000 0.817300 0.576200 +usemtl None +s off +f 2/1/1 4/2/1 3/3/1 1/4/1 +f 4/4/2 8/5/2 7/6/2 3/1/2 +f 8/7/3 6/8/3 5/9/3 7/10/3 +f 6/2/4 2/9/4 1/8/4 5/3/4 +f 1/9/5 3/10/5 7/11/5 5/12/5 +f 6/6/6 8/1/6 4/13/6 2/14/6 +f 10/1/1 12/2/1 11/3/1 9/4/1 +f 12/2/2 16/9/2 15/8/2 11/3/2 +f 16/7/3 14/8/3 13/9/3 15/10/3 +f 14/4/4 10/5/4 9/6/4 13/1/4 +f 9/12/5 11/11/5 15/15/5 13/16/5 +f 14/14/6 16/13/6 12/17/6 10/18/6 +f 20/2/3 24/3/3 23/19/3 19/20/3 +f 22/1/1 18/4/1 17/21/1 21/22/1 +f 17/23/5 19/24/5 23/25/5 21/26/5 +f 22/21/6 24/5/6 20/6/6 18/22/6 +f 28/27/3 32/28/3 31/29/3 27/30/3 +f 30/31/1 26/32/1 25/33/1 29/34/1 +f 25/35/7 27/10/7 31/7/7 29/36/7 +f 30/37/8 32/38/8 28/39/8 26/40/8 +f 17/41/2 18/42/2 20/43/2 19/44/2 diff --git a/mods/doors/sounds/doors_door_close.ogg b/mods/doors/sounds/doors_door_close.ogg new file mode 100644 index 0000000..fede4af Binary files /dev/null and b/mods/doors/sounds/doors_door_close.ogg differ diff --git a/mods/doors/sounds/doors_door_open.ogg b/mods/doors/sounds/doors_door_open.ogg new file mode 100644 index 0000000..9a4c4f1 Binary files /dev/null and b/mods/doors/sounds/doors_door_open.ogg differ diff --git a/mods/doors/sounds/doors_fencegate_close.ogg b/mods/doors/sounds/doors_fencegate_close.ogg new file mode 100644 index 0000000..d42590f Binary files /dev/null and b/mods/doors/sounds/doors_fencegate_close.ogg differ diff --git a/mods/doors/sounds/doors_fencegate_open.ogg b/mods/doors/sounds/doors_fencegate_open.ogg new file mode 100644 index 0000000..f6dfd1d Binary files /dev/null and b/mods/doors/sounds/doors_fencegate_open.ogg differ diff --git a/mods/doors/sounds/doors_glass_door_close.ogg b/mods/doors/sounds/doors_glass_door_close.ogg new file mode 100644 index 0000000..b3c1355 Binary files /dev/null and b/mods/doors/sounds/doors_glass_door_close.ogg differ diff --git a/mods/doors/sounds/doors_glass_door_open.ogg b/mods/doors/sounds/doors_glass_door_open.ogg new file mode 100644 index 0000000..66e6812 Binary files /dev/null and b/mods/doors/sounds/doors_glass_door_open.ogg differ diff --git a/mods/doors/sounds/doors_steel_door_close.ogg b/mods/doors/sounds/doors_steel_door_close.ogg new file mode 100644 index 0000000..aea7be6 Binary files /dev/null and b/mods/doors/sounds/doors_steel_door_close.ogg differ diff --git a/mods/doors/sounds/doors_steel_door_open.ogg b/mods/doors/sounds/doors_steel_door_open.ogg new file mode 100644 index 0000000..de87477 Binary files /dev/null and b/mods/doors/sounds/doors_steel_door_open.ogg differ diff --git a/mods/doors/textures/doors_blank.png b/mods/doors/textures/doors_blank.png new file mode 100644 index 0000000..1914264 Binary files /dev/null and b/mods/doors/textures/doors_blank.png differ diff --git a/mods/doors/textures/doors_door_glass.png b/mods/doors/textures/doors_door_glass.png new file mode 100644 index 0000000..3c205dd Binary files /dev/null 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 new file mode 100644 index 0000000..07ac5b2 Binary files /dev/null and b/mods/doors/textures/doors_door_obsidian_glass.png differ diff --git a/mods/doors/textures/doors_door_steel.png b/mods/doors/textures/doors_door_steel.png new file mode 100644 index 0000000..f42f335 Binary files /dev/null and b/mods/doors/textures/doors_door_steel.png differ diff --git a/mods/doors/textures/doors_door_wood.png b/mods/doors/textures/doors_door_wood.png new file mode 100644 index 0000000..7b18203 Binary files /dev/null and b/mods/doors/textures/doors_door_wood.png differ diff --git a/mods/doors/textures/doors_item_glass.png b/mods/doors/textures/doors_item_glass.png new file mode 100644 index 0000000..49a300f Binary files /dev/null and b/mods/doors/textures/doors_item_glass.png differ diff --git a/mods/doors/textures/doors_item_obsidian_glass.png b/mods/doors/textures/doors_item_obsidian_glass.png new file mode 100644 index 0000000..1026d43 Binary files /dev/null and b/mods/doors/textures/doors_item_obsidian_glass.png differ diff --git a/mods/doors/textures/doors_item_steel.png b/mods/doors/textures/doors_item_steel.png new file mode 100644 index 0000000..dd99e13 Binary files /dev/null and b/mods/doors/textures/doors_item_steel.png differ diff --git a/mods/doors/textures/doors_item_wood.png b/mods/doors/textures/doors_item_wood.png new file mode 100644 index 0000000..d3a62ab Binary files /dev/null and b/mods/doors/textures/doors_item_wood.png differ diff --git a/mods/doors/textures/doors_trapdoor.png b/mods/doors/textures/doors_trapdoor.png new file mode 100644 index 0000000..e92c8b2 Binary files /dev/null and b/mods/doors/textures/doors_trapdoor.png differ diff --git a/mods/doors/textures/doors_trapdoor_side.png b/mods/doors/textures/doors_trapdoor_side.png new file mode 100644 index 0000000..4a8b99f Binary files /dev/null and b/mods/doors/textures/doors_trapdoor_side.png differ diff --git a/mods/doors/textures/doors_trapdoor_steel.png b/mods/doors/textures/doors_trapdoor_steel.png new file mode 100644 index 0000000..4ba507d Binary files /dev/null and b/mods/doors/textures/doors_trapdoor_steel.png differ diff --git a/mods/doors/textures/doors_trapdoor_steel_side.png b/mods/doors/textures/doors_trapdoor_steel_side.png new file mode 100644 index 0000000..44c4344 Binary files /dev/null and b/mods/doors/textures/doors_trapdoor_steel_side.png differ diff --git a/mods/dresser/AUTHORS b/mods/dresser/AUTHORS new file mode 100644 index 0000000..55f8daf --- /dev/null +++ b/mods/dresser/AUTHORS @@ -0,0 +1,7 @@ +Blass by blassdeskywars: CC BY-NC-SA (3.0) +Urotsuki by 2ch: CC 0 (1.0) +Temerlime by Temerario: CC BY-SA (3.0) +Me Only by ourhouseisapie: CC 0 (1.0) +Blockcolor by Chiantos: CC BY-SA (3.0) +Cheapie by lovehart: CC BY-SA (3.0) +Winter II Sam by Jordach: CC BY-SA (3.0) diff --git a/mods/dresser/README b/mods/dresser/README new file mode 100644 index 0000000..2e774c6 --- /dev/null +++ b/mods/dresser/README @@ -0,0 +1,3 @@ +Dress mod for Glitchtest game +Copyright 2018 James Stevenson +GNU GPL 3 diff --git a/mods/dresser/init.lua b/mods/dresser/init.lua new file mode 100644 index 0000000..876f6d7 --- /dev/null +++ b/mods/dresser/init.lua @@ -0,0 +1,144 @@ +-- Dresser mod for Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + + +dresser = {} +dresser.players = {} +dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/skins.lua") +local function formspec(name) + local player = minetest.get_player_by_name(name) + if not player then + return + end + player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = -10, z = 0}) + dresser.players[name] = true + return "size[8,10.5]" .. + "no_prepend[]" .. + "bgcolor[#FFFFFF00]" .. + "box[-0.15,-0.15;8,1.2;#000000FF]" .. -- Top border + "box[6.85,-0.15;1.1,11.2;#000000FF]" .. -- Right border + "box[-0.15,6.85;8.1,4.2;#000000FF]" .. -- Bottom border + "box[-0.15,-0.15;1.1,10;#000000FF]" .. -- Left border + "box[-0.1,-0.1;1,10;#343434FF]" .. -- Left + "box[-0.1,-0.1;8,1.1;#343434FF]" .. -- Top + "box[6.9,-0.1;1,10;#343434FF]" .. -- Right + "box[-0.1,6.9;8,4.1;#343434FF]" .. -- Bottom + "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" .. + jas0.help_button() .. + jas0.exit_button() .. + "list[current_player;skin;3.5,0;1,1]" .. + "list[detached:" .. name .. "_clothing;clothing;0,1;1,6]" .. + "list[detached:" .. name .. "_armor;armor;7,1;1,6]" .. + "list[current_player;main;0,7;8,4]" .. + "" +end + +local dresser_help = "The dresser can be used to change clothing, " .. + "armor, and skins. Use third person view to check yourself out!" .. + "\n\nThe clothing goes on the left side, and the armor on the right. " .. + "The skin goes on top. Armor, skins, and clothing, can be applied " .. + "by swinging the items in your hand!" .. +"" + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "dresser:dresser" then + return + end + if fields.quit then + player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + dresser.players[player:get_player_name()] = nil + if fields.help then + jas0.message(player, dresser_help, true, nil, "Dresser Help", true) + end + end +end) +minetest.register_on_joinplayer(function(player) + if not player then + return + end + local inv = player:get_inventory() + inv:set_size("skin", 1) +end) +minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) + if action == "move" then + if inventory_info.from_list == "main" and inventory_info.to_list == "skin" then + if inventory:get_stack(inventory_info.from_list, + inventory_info.from_index):get_definition()._skin then + return 1 + else + return 0 + end + end + end +end) +minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info) + if action == "move" and inventory_info.to_list == "skin" then + local skin = inventory:get_stack("skin", 1):get_definition()._skin + if skin then + multiskin.set_player_skin(player, skin) + multiskin.update_player_visuals(player) + end + elseif (action == "move" and + inventory_info.from_list == "skin") or + (action == "take" and + inventory_info.listname == "skin") then + local gender = player:get_meta():get_string("gender") + local skin = "multiskin_" .. gender .. ".png" + if skin ~= player:get_meta():get_string("multiskin_skin") then + multiskin.set_player_skin(player, skin) + multiskin.update_player_visuals(player) + end + end +end) +minetest.register_on_respawnplayer(function(player) + if not player then + return + end + player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) +end) +minetest.register_on_dieplayer(function(player) + if not player then + return + end + dresser.players[player:get_player_name()] = nil +end) +minetest.register_on_leaveplayer(function(player) + if not player then + return + end + dresser.players[player:get_player_name()] = nil +end) +minetest.register_craft({ + output = "dresser:dresser", + recipe = { + {"group:wool", "group:wool", "group:wool"}, + {"group:wool", "default:chest", "group:wool"}, + {"group:wool", "group:wool", "group:wool"}, + }, +}) +minetest.register_node("dresser:dresser", { + description = "Dresser", + paramtype2 = "facedir", + tiles = { + "default_wood.png", + "default_wood.png", + "default_wood.png", + "default_wood.png", + "dresser_dresser.png", + "dresser_dresser.png", + }, + sounds = default.node_sound_wood_defaults(), + groups = {choppy = 3, flammable = 3}, + on_construct = function(pos) + minetest.get_meta(pos):set_string("infotext", "Dresser") + end, + on_use = function(itemstack, user, pointed_thing) + local name = user:get_player_name() + minetest.show_formspec(name, "dresser:dresser", formspec(name)) + end, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local name = clicker:get_player_name() + minetest.show_formspec(name, "dresser:dresser", formspec(name)) + end, +}) diff --git a/mods/dresser/skins.lua b/mods/dresser/skins.lua new file mode 100644 index 0000000..3f83c27 --- /dev/null +++ b/mods/dresser/skins.lua @@ -0,0 +1,37 @@ +dresser.skins = { + {"blass", "Blass"}, + {"urotsuki", "Urotsuki"}, + {"temerlime", "Temerlime"}, + {"me_only", "Me Only"}, + {"blockcolor", "Blockcolor"}, + {"cheapie", "Cheapie"}, + {"sam_ii_winter", "Winter Sam"}, +} + +minetest.register_alias("jas0:skin_character", "dresser:skin_blass") +minetest.register_alias("dresser:skin_dusty", "dresser:skin_blass") + +for i = 1, #dresser.skins do + local file = dresser.skins[i][1] + local name = dresser.skins[i][2] + minetest.register_alias("jas0:skin_" .. file, + "dresser:skin_" .. file) + minetest.register_craftitem("dresser:skin_" .. file, { + description = name, + inventory_image = "multiskin_" .. file .. "_inv.png", + stack_max = 1, + on_use = function(itemstack, user, pointed_thing) + multiskin.set_player_skin(user, + "multiskin_" .. file .. ".png") + multiskin.update_player_visuals(user) + local inv = user:get_inventory() + if not inv:is_empty("skin", 1) then + local object = minetest.add_item(user:get_pos(), inv:get_stack("skin", 1)) + inv:set_list("skin", {}) + end + inv:add_item("skin", itemstack) + return "" + end, + _skin = "multiskin_" .. file .. ".png", + }) +end diff --git a/mods/dresser/textures/dresser_dresser.png b/mods/dresser/textures/dresser_dresser.png new file mode 100644 index 0000000..b3f3cce Binary files /dev/null and b/mods/dresser/textures/dresser_dresser.png differ diff --git a/mods/dungeon_loot/README.txt b/mods/dungeon_loot/README.txt new file mode 100644 index 0000000..c500d25 --- /dev/null +++ b/mods/dungeon_loot/README.txt @@ -0,0 +1,11 @@ +Minetest Game mod: dungeon_loot +=============================== +Adds randomly generated chests with some "loot" to generated dungeons, +an API to register additional loot is provided. +Only works if dungeons are actually enabled in mapgen flags. + +License information can be found in license.txt + +Authors of source code +---------------------- +Originally by sfan5 (MIT) diff --git a/mods/dungeon_loot/depends.txt b/mods/dungeon_loot/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/dungeon_loot/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/dungeon_loot/init.lua b/mods/dungeon_loot/init.lua new file mode 100644 index 0000000..9d8ac52 --- /dev/null +++ b/mods/dungeon_loot/init.lua @@ -0,0 +1,8 @@ +dungeon_loot = {} + +dungeon_loot.CHESTS_MIN = 0 -- not necessarily in a single dungeon +dungeon_loot.CHESTS_MAX = 2 +dungeon_loot.STACKS_PER_CHEST_MAX = 8 + +dofile(minetest.get_modpath("dungeon_loot") .. "/loot.lua") +dofile(minetest.get_modpath("dungeon_loot") .. "/mapgen.lua") diff --git a/mods/dungeon_loot/license.txt b/mods/dungeon_loot/license.txt new file mode 100644 index 0000000..0af30a0 --- /dev/null +++ b/mods/dungeon_loot/license.txt @@ -0,0 +1,24 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2017 sfan5 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT diff --git a/mods/dungeon_loot/loot.lua b/mods/dungeon_loot/loot.lua new file mode 100644 index 0000000..3fe0bff --- /dev/null +++ b/mods/dungeon_loot/loot.lua @@ -0,0 +1,62 @@ +dungeon_loot.registered_loot = { + -- buckets + {name = "bucket:bucket_empty", chance = 0.55}, + -- water in deserts or above ground, lava otherwise + {name = "bucket:bucket_water", chance = 0.45, types = {"sandstone", "desert"}}, + {name = "bucket:bucket_water", chance = 0.45, y = {0, 32768}, types = {"normal"}}, + {name = "bucket:bucket_lava", chance = 0.45, y = {-32768, -1}, types = {"normal"}}, + + -- various items + {name = "default:stick", chance = 0.6, count = {3, 6}}, + {name = "default:flint", chance = 0.4, count = {1, 3}}, + {name = "vessels:glass_fragments", chance = 0.35, count = {1, 4}}, + {name = "carts:rail", chance = 0.35, count = {1, 6}}, + + -- farming / consumable + {name = "farming:string", chance = 0.5, count = {1, 8}}, + {name = "farming:wheat", chance = 0.5, count = {2, 5}}, + {name = "default:apple", chance = 0.4, count = {1, 4}}, + {name = "farming:seed_cotton", chance = 0.4, count = {1, 4}, types = {"normal"}}, + {name = "default:cactus", chance = 0.4, count = {1, 4}, types = {"sandstone", "desert"}}, + + -- minerals + {name = "default:coal_lump", chance = 0.9, count = {1, 12}}, + {name = "default:gold_ingot", chance = 0.5}, + {name = "default:steel_ingot", chance = 0.4, count = {1, 6}}, + {name = "default:mese_crystal", chance = 0.1, count = {2, 3}}, + + -- tools + {name = "default:sword_wood", chance = 0.6}, + {name = "default:pick_stone", chance = 0.3}, + {name = "default:axe_diamond", chance = 0.05}, + + -- natural materials + {name = "default:sand", chance = 0.8, count = {4, 32}, y = {-64, 32768}, types = {"normal"}}, + {name = "default:desert_sand", chance = 0.8, count = {4, 32}, y = {-64, 32768}, types = {"sandstone"}}, + {name = "default:desert_cobble", chance = 0.8, count = {4, 32}, types = {"desert"}}, + {name = "default:dirt", chance = 0.6, count = {2, 16}, y = {-64, 32768}}, + {name = "default:obsidian", chance = 0.25, count = {1, 3}, y = {-32768, -512}}, + {name = "default:mese", chance = 0.15, y = {-32768, -512}}, +} + +function dungeon_loot.register(t) + if t.name ~= nil then + t = {t} -- single entry + end + for _, loot in ipairs(t) do + table.insert(dungeon_loot.registered_loot, loot) + end +end + +function dungeon_loot._internal_get_loot(pos_y, dungeontype) + -- filter by y pos and type + local ret = {} + for _, l in ipairs(dungeon_loot.registered_loot) do + if l.y == nil or (pos_y >= l.y[1] and pos_y <= l.y[2]) then + if l.types == nil or table.indexof(l.types, dungeontype) ~= -1 then + table.insert(ret, l) + end + end + end + return ret +end diff --git a/mods/dungeon_loot/mapgen.lua b/mods/dungeon_loot/mapgen.lua new file mode 100644 index 0000000..c6a4509 --- /dev/null +++ b/mods/dungeon_loot/mapgen.lua @@ -0,0 +1,168 @@ +minetest.set_gen_notify({dungeon = true, temple = true}) + +local function noise3d_integer(noise, pos) + return math.abs(math.floor(noise:get_3d(pos) * 0x7fffffff)) +end + +local function random_sample(rand, list, count) + local ret = {} + for n = 1, count do + local idx = rand:next(1, #list) + table.insert(ret, list[idx]) + table.remove(list, idx) + end + return ret +end + +local function find_walls(cpos) + local wall = minetest.registered_aliases["mapgen_cobble"] + local wall_alt = minetest.registered_aliases["mapgen_mossycobble"] + local wall_ss = minetest.registered_aliases["mapgen_sandstonebrick"] + local wall_ds = minetest.registered_aliases["mapgen_desert_stone"] + local is_wall = function(node) + return table.indexof({wall, wall_alt, wall_ss, wall_ds}, node.name) ~= -1 + end + + local dirs = {{x=1, z=0}, {x=-1, z=0}, {x=0, z=1}, {x=0, z=-1}} + local get_node = minetest.get_node + + local ret = {} + local mindist = {x=0, z=0} + local min = function(a, b) return a ~= 0 and math.min(a, b) or b end + local wallnode + for _, dir in ipairs(dirs) do + for i = 1, 9 do -- 9 = max room size / 2 + local pos = vector.add(cpos, {x=dir.x*i, y=0, z=dir.z*i}) + + -- continue in that direction until we find a wall-like node + local node = get_node(pos) + if is_wall(node) then + local front_below = vector.subtract(pos, {x=dir.x, y=1, z=dir.z}) + local above = vector.add(pos, {x=0, y=1, z=0}) + + -- check that it: + --- is at least 2 nodes high (not a staircase) + --- has a floor + if is_wall(get_node(front_below)) and is_wall(get_node(above)) then + table.insert(ret, {pos = pos, facing = {x=-dir.x, y=0, z=-dir.z}}) + if dir.z == 0 then + mindist.x = min(mindist.x, i-1) + else + mindist.z = min(mindist.z, i-1) + end + wallnode = node.name + end + -- abort even if it wasn't a wall cause something is in the way + break + end + end + end + + local mapping = { + [wall_ss] = "sandstone", + [wall_ds] = "desert" + } + return { + walls = ret, + size = {x=mindist.x*2, z=mindist.z*2}, + type = mapping[wallnode] or "normal" + } +end + +local function populate_chest(pos, rand, dungeontype) + --minetest.chat_send_all("chest placed at " .. minetest.pos_to_string(pos) .. " [" .. dungeontype .. "]") + --minetest.add_node(vector.add(pos, {x=0, y=1, z=0}), {name="default:torch", param2=1}) + + local item_list = dungeon_loot._internal_get_loot(pos.y, dungeontype) + -- take random (partial) sample of all possible items + assert(#item_list >= dungeon_loot.STACKS_PER_CHEST_MAX) + item_list = random_sample(rand, item_list, dungeon_loot.STACKS_PER_CHEST_MAX) + + -- apply chances / randomized amounts and collect resulting items + local items = {} + for _, loot in ipairs(item_list) do + if rand:next(0, 1000) / 1000 <= loot.chance then + local itemdef = minetest.registered_items[loot.name] + local amount = 1 + if loot.count ~= nil then + amount = rand:next(loot.count[1], loot.count[2]) + end + + if itemdef.tool_capabilities then + for n = 1, amount do + local wear = rand:next(0.20 * 65535, 0.75 * 65535) -- 20% to 75% wear + table.insert(items, ItemStack({name = loot.name, wear = wear})) + end + elseif itemdef.stack_max == 1 then + -- not stackable, add separately + for n = 1, amount do + table.insert(items, loot.name) + end + else + table.insert(items, ItemStack({name = loot.name, count = amount})) + end + end + end + + -- place items at random places in chest + local inv = minetest.get_meta(pos):get_inventory() + local listsz = inv:get_size("main") + assert(listsz >= #items) + for _, item in ipairs(items) do + local index = rand:next(1, listsz) + if inv:get_stack("main", index):is_empty() then + inv:set_stack("main", index, item) + else + inv:add_item("main", item) -- space occupied, just put it anywhere + end + end +end + + +minetest.register_on_generated(function(minp, maxp, blockseed) + local gennotify = minetest.get_mapgen_object("gennotify") + local poslist = gennotify["dungeon"] or {} + for _, entry in ipairs(gennotify["temple"] or {}) do + table.insert(poslist, entry) + end + if #poslist == 0 then return end + + local noise = minetest.get_perlin(10115, 4, 0.5, 1) + local rand = PcgRandom(noise3d_integer(noise, poslist[1])) + + local candidates = {} + -- process at most 8 rooms to keep runtime of this predictable + local num_process = math.min(#poslist, 8) + for i = 1, num_process do + local room = find_walls(poslist[i]) + -- skip small rooms and everything that doesn't at least have 3 walls + if math.min(room.size.x, room.size.z) >= 4 and #room.walls >= 3 then + table.insert(candidates, room) + end + end + + local num_chests = rand:next(dungeon_loot.CHESTS_MIN, dungeon_loot.CHESTS_MAX) + num_chests = math.min(#candidates, num_chests) + local rooms = random_sample(rand, candidates, num_chests) + + for _, room in ipairs(rooms) do + -- choose place somewhere in front of any of the walls + local wall = room.walls[rand:next(1, #room.walls)] + local v, vi -- vector / axis that runs alongside the wall + if wall.facing.x ~= 0 then + v, vi = {x=0, y=0, z=1}, "z" + else + v, vi = {x=1, y=0, z=0}, "x" + end + local chestpos = vector.add(wall.pos, wall.facing) + local off = rand:next(-room.size[vi]/2 + 1, room.size[vi]/2 - 1) + chestpos = vector.add(chestpos, vector.multiply(v, off)) + + if minetest.get_node(chestpos).name == "air" then + -- make it face inwards to the room + local facedir = minetest.dir_to_facedir(vector.multiply(wall.facing, -1)) + minetest.add_node(chestpos, {name = "default:chest", param2 = facedir}) + populate_chest(chestpos, PcgRandom(noise3d_integer(noise, chestpos)), room.type) + end + end +end) diff --git a/mods/dye/README.txt b/mods/dye/README.txt new file mode 100644 index 0000000..a2fbdd2 --- /dev/null +++ b/mods/dye/README.txt @@ -0,0 +1,13 @@ +Minetest Game mod: dye +====================== +See license.txt for license information. +See init.lua for documentation. + +Authors of source code +---------------------- +Originally by Perttu Ahola (celeron55) (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +Perttu Ahola (celeron55) (CC BY-SA 3.0) diff --git a/mods/dye/depends.txt b/mods/dye/depends.txt new file mode 100644 index 0000000..e69de29 diff --git a/mods/dye/init.lua b/mods/dye/init.lua new file mode 100644 index 0000000..c259811 --- /dev/null +++ b/mods/dye/init.lua @@ -0,0 +1,97 @@ +dye = {} + +-- Make dye names and descriptions available globally + +dye.dyes = { + {"white", "White"}, + {"grey", "Grey"}, + {"dark_grey", "Dark grey"}, + {"black", "Black"}, + {"violet", "Violet"}, + {"blue", "Blue"}, + {"cyan", "Cyan"}, + {"dark_green", "Dark green"}, + {"green", "Green"}, + {"yellow", "Yellow"}, + {"brown", "Brown"}, + {"orange", "Orange"}, + {"red", "Red"}, + {"magenta", "Magenta"}, + {"pink", "Pink"}, +} + +-- Define items + +for _, row in ipairs(dye.dyes) do + local name = row[1] + local description = row[2] + local groups = {dye = 1} + groups["color_" .. name] = 1 + + minetest.register_craftitem("dye:" .. name, { + inventory_image = "dye_" .. name .. ".png", + description = description .. " Dye", + groups = groups + }) + + minetest.register_craft({ + type = "shapeless", + output = "dye:" .. name .. " 4", + recipe = {"group:flower,color_" .. name}, + }) +end + +-- Manually add coal -> black dye + +minetest.register_craft({ + type = "shapeless", + output = "dye:black 4", + recipe = {"group:coal"}, +}) + +-- Manually add blueberries->violet dye + +minetest.register_craft({ + type = "shapeless", + output = "dye:violet 2", + recipe = {"default:blueberries"}, +}) + +-- Mix recipes + +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 _, 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/dye/license.txt b/mods/dye/license.txt new file mode 100644 index 0000000..bf9d350 --- /dev/null +++ b/mods/dye/license.txt @@ -0,0 +1,60 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) + +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/dye/textures/dye_black.png b/mods/dye/textures/dye_black.png new file mode 100644 index 0000000..1055b6c Binary files /dev/null and b/mods/dye/textures/dye_black.png differ diff --git a/mods/dye/textures/dye_blue.png b/mods/dye/textures/dye_blue.png new file mode 100644 index 0000000..d1377c6 Binary files /dev/null and b/mods/dye/textures/dye_blue.png differ diff --git a/mods/dye/textures/dye_brown.png b/mods/dye/textures/dye_brown.png new file mode 100644 index 0000000..77d475c Binary files /dev/null and b/mods/dye/textures/dye_brown.png differ diff --git a/mods/dye/textures/dye_cyan.png b/mods/dye/textures/dye_cyan.png new file mode 100644 index 0000000..239d66c Binary files /dev/null and b/mods/dye/textures/dye_cyan.png differ diff --git a/mods/dye/textures/dye_dark_green.png b/mods/dye/textures/dye_dark_green.png new file mode 100644 index 0000000..9606ccf Binary files /dev/null and b/mods/dye/textures/dye_dark_green.png differ diff --git a/mods/dye/textures/dye_dark_grey.png b/mods/dye/textures/dye_dark_grey.png new file mode 100644 index 0000000..060737b Binary files /dev/null and b/mods/dye/textures/dye_dark_grey.png differ diff --git a/mods/dye/textures/dye_green.png b/mods/dye/textures/dye_green.png new file mode 100644 index 0000000..0d99ee1 Binary files /dev/null and b/mods/dye/textures/dye_green.png differ diff --git a/mods/dye/textures/dye_grey.png b/mods/dye/textures/dye_grey.png new file mode 100644 index 0000000..5efb028 Binary files /dev/null and b/mods/dye/textures/dye_grey.png differ diff --git a/mods/dye/textures/dye_magenta.png b/mods/dye/textures/dye_magenta.png new file mode 100644 index 0000000..c84df62 Binary files /dev/null and b/mods/dye/textures/dye_magenta.png differ diff --git a/mods/dye/textures/dye_orange.png b/mods/dye/textures/dye_orange.png new file mode 100644 index 0000000..0844907 Binary files /dev/null and b/mods/dye/textures/dye_orange.png differ diff --git a/mods/dye/textures/dye_pink.png b/mods/dye/textures/dye_pink.png new file mode 100644 index 0000000..c3dec22 Binary files /dev/null and b/mods/dye/textures/dye_pink.png differ diff --git a/mods/dye/textures/dye_red.png b/mods/dye/textures/dye_red.png new file mode 100644 index 0000000..14eafbf Binary files /dev/null and b/mods/dye/textures/dye_red.png differ diff --git a/mods/dye/textures/dye_violet.png b/mods/dye/textures/dye_violet.png new file mode 100644 index 0000000..600cbb4 Binary files /dev/null and b/mods/dye/textures/dye_violet.png differ diff --git a/mods/dye/textures/dye_white.png b/mods/dye/textures/dye_white.png new file mode 100644 index 0000000..2a840a4 Binary files /dev/null and b/mods/dye/textures/dye_white.png differ diff --git a/mods/dye/textures/dye_yellow.png b/mods/dye/textures/dye_yellow.png new file mode 100644 index 0000000..fe75775 Binary files /dev/null and b/mods/dye/textures/dye_yellow.png differ diff --git a/mods/farming/README.txt b/mods/farming/README.txt new file mode 100644 index 0000000..d46748d --- /dev/null +++ b/mods/farming/README.txt @@ -0,0 +1,40 @@ +Minetest Game mod: farming +========================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by PilzAdam (MIT) +webdesigner97 (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +Created by PilzAdam (CC BY 3.0): + farming_bread.png + farming_soil.png + farming_soil_wet.png + farming_soil_wet_side.png + farming_string.png + +Created by BlockMen (CC BY 3.0): + farming_tool_diamondhoe.png + farming_tool_mesehoe.png + farming_tool_bronzehoe.png + farming_tool_steelhoe.png + farming_tool_stonehoe.png + farming_tool_woodhoe.png + +Created by MasterGollum (CC BY 3.0): + farming_straw.png + +Created by Gambit (CC BY 3.0): + farming_wheat.png + farming_wheat_*.png + farming_cotton_*.png + farming_flour.png + farming_cotton_seed.png + farming_wheat_seed.png + +Created by Napiophelios (CC BY-SA 3.0): + farming_cotton.png diff --git a/mods/farming/api.lua b/mods/farming/api.lua new file mode 100644 index 0000000..1c613a6 --- /dev/null +++ b/mods/farming/api.lua @@ -0,0 +1,391 @@ + +-- Wear out hoes, place soil +-- TODO Ignore group:flower +farming.registered_plants = {} + +farming.hoe_on_use = function(itemstack, user, pointed_thing, uses) + local pt = pointed_thing + -- check if pointing at a node + if not pt then + return + end + if pt.type ~= "node" then + return + end + + local under = minetest.get_node(pt.under) + local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z} + local above = minetest.get_node(p) + + -- return if any of the nodes is not registered + if not minetest.registered_nodes[under.name] then + return + end + if not minetest.registered_nodes[above.name] then + return + end + + -- check if the node above the pointed thing is air + if above.name ~= "air" then + return + end + + -- check if pointing at soil + if minetest.get_item_group(under.name, "soil") ~= 1 then + return + end + + -- check if (wet) soil defined + local regN = minetest.registered_nodes + if regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then + return + end + + if minetest.is_protected(pt.under, user:get_player_name()) then + minetest.record_protection_violation(pt.under, user:get_player_name()) + return + end + if minetest.is_protected(pt.above, user:get_player_name()) then + minetest.record_protection_violation(pt.above, user:get_player_name()) + return + end + + -- turn the node into soil and play sound + minetest.set_node(pt.under, {name = regN[under.name].soil.dry}) + minetest.sound_play("default_dig_crumbly", { + pos = pt.under, + gain = 0.5, + }) + + 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)) + -- 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}) + end + end + return itemstack +end + +-- Register new hoes +farming.register_hoe = function(name, def) + -- Check for : prefix (register new hoes in your mod's namespace) + if name:sub(1,1) ~= ":" then + name = ":" .. name + end + -- Check def table + if def.description == nil then + def.description = "Hoe" + end + if def.inventory_image == nil then + def.inventory_image = "unknown_item.png" + end + if def.max_uses == nil then + def.max_uses = 30 + end + -- Register the tool + minetest.register_tool(name, { + description = def.description, + inventory_image = def.inventory_image, + on_use = function(itemstack, user, pointed_thing) + return farming.hoe_on_use(itemstack, user, pointed_thing, def.max_uses) + end, + groups = def.groups, + sound = {breaks = "default_tool_breaks"}, + }) + -- Register its recipe + if def.recipe then + minetest.register_craft({ + output = name:sub(2), + recipe = def.recipe + }) + elseif def.material then + minetest.register_craft({ + output = name:sub(2), + recipe = { + {def.material, def.material, ""}, + {"", "group:stick", ""}, + {"", "group:stick", ""} + } + }) + end +end + +-- how often node timers for plants will tick, +/- some random value +local function tick(pos) + minetest.get_node_timer(pos):start(math.random(166, 286)) +end +-- how often a growth failure tick is retried (e.g. too dark) +local function tick_again(pos) + minetest.get_node_timer(pos):start(math.random(40, 80)) +end + +-- Seed placement +farming.place_seed = function(itemstack, placer, pointed_thing, plantname) + local pt = pointed_thing + -- check if pointing at a node + if not pt then + return itemstack + end + if pt.type ~= "node" then + return itemstack + end + + local under = minetest.get_node(pt.under) + local above = minetest.get_node(pt.above) + + local player_name = placer and placer:get_player_name() or "" + + if minetest.is_protected(pt.under, player_name) then + minetest.record_protection_violation(pt.under, player_name) + return + end + if minetest.is_protected(pt.above, player_name) then + minetest.record_protection_violation(pt.above, player_name) + return + end + + -- return if any of the nodes is not registered + if not minetest.registered_nodes[under.name] then + return itemstack + end + if not minetest.registered_nodes[above.name] then + return itemstack + end + + -- check if pointing at the top of the node + if pt.above.y ~= pt.under.y+1 then + return itemstack + end + + -- check if you can replace the node above the pointed node + if not minetest.registered_nodes[above.name].buildable_to then + return itemstack + end + + -- check if pointing at soil + if minetest.get_item_group(under.name, "soil") < 2 then + return itemstack + end + + -- add the node and remove 1 item from the itemstack + minetest.add_node(pt.above, {name = plantname, param2 = 1}) + tick(pt.above) + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + return itemstack +end + +farming.grow_plant = function(pos, elapsed) + local node = minetest.get_node(pos) + local name = node.name + local def = minetest.registered_nodes[name] + + if not def.next_plant then + -- disable timer for fully grown plant + return + end + + -- grow seed + if minetest.get_item_group(node.name, "seed") and def.fertility then + local soil_node = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z}) + if not soil_node then + tick_again(pos) + return + end + -- omitted is a check for light, we assume seeds can germinate in the dark. + for _, v in pairs(def.fertility) do + if minetest.get_item_group(soil_node.name, v) ~= 0 then + local placenode = {name = def.next_plant} + if def.place_param2 then + placenode.param2 = def.place_param2 + end + minetest.swap_node(pos, placenode) + if minetest.registered_nodes[def.next_plant].next_plant then + tick(pos) + return + end + end + end + + return + end + + -- check if on wet soil + local below = minetest.get_node({x = pos.x, y = pos.y - 1, z = pos.z}) + if minetest.get_item_group(below.name, "soil") < 3 then + tick_again(pos) + return + end + + -- check light + local light = minetest.get_node_light(pos) + if not light or light < def.minlight or light > def.maxlight then + tick_again(pos) + return + end + + -- grow + local placenode = {name = def.next_plant} + if def.place_param2 then + placenode.param2 = def.place_param2 + end + minetest.swap_node(pos, placenode) + + -- new timer needed? + if minetest.registered_nodes[def.next_plant].next_plant then + tick(pos) + end + return +end + +-- Register plants +farming.register_plant = function(name, def) + local mname = name:split(":")[1] + local pname = name:split(":")[2] + + -- Check def table + if not def.description then + def.description = "Seed" + end + if not def.inventory_image then + def.inventory_image = "unknown_item.png" + end + if not def.steps then + return nil + end + if not def.minlight then + def.minlight = 1 + end + if not def.maxlight then + def.maxlight = 14 + end + if not def.fertility then + def.fertility = {} + end + + farming.registered_plants[pname] = def + + -- Register seed + local lbm_nodes = {mname .. ":seed_" .. pname} + local g = {seed = 1, snappy = 3, attached_node = 1, flammable = 2} + for k, v in pairs(def.fertility) do + g[v] = 1 + end + minetest.register_node(":" .. mname .. ":seed_" .. pname, { + description = def.description, + tiles = {def.inventory_image}, + inventory_image = def.inventory_image, + wield_image = def.inventory_image, + drawtype = "signlike", + groups = g, + paramtype = "light", + paramtype2 = "wallmounted", + place_param2 = def.place_param2 or nil, -- this isn't actually used for placement + walkable = false, + sunlight_propagates = true, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, + }, + fertility = def.fertility, + sounds = default.node_sound_dirt_defaults({ + dig = {name = "", gain = 0}, + dug = {name = "default_grass_footstep", gain = 0.2}, + place = {name = "default_place_node", gain = 0.25}, + }), + + 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:is_player() 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", + on_timer = farming.grow_plant, + minlight = def.minlight, + maxlight = def.maxlight, + }) + + -- Register harvest + minetest.register_craftitem(":" .. mname .. ":" .. pname, { + description = pname:gsub("^%l", string.upper), + inventory_image = mname .. "_" .. pname .. ".png", + groups = def.groups or {flammable = 2}, + }) + + -- 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 = 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} + nodegroups[pname] = i + + local next_plant = nil + + if i < def.steps then + next_plant = mname .. ":" .. pname .. "_" .. (i + 1) + lbm_nodes[#lbm_nodes + 1] = mname .. ":" .. pname .. "_" .. i + end + + minetest.register_node(":" .. mname .. ":" .. pname .. "_" .. i, { + drawtype = "plantlike", + waving = 1, + tiles = {mname .. "_" .. pname .. "_" .. i .. ".png"}, + paramtype = "light", + paramtype2 = def.paramtype2 or nil, + place_param2 = def.place_param2 or nil, + walkable = false, + buildable_to = true, + drop = drop, + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}, + }, + groups = nodegroups, + sounds = default.node_sound_leaves_defaults(), + next_plant = next_plant, + on_timer = farming.grow_plant, + minlight = def.minlight, + maxlight = def.maxlight, + }) + end + + -- replacement LBM for pre-nodetimer plants + minetest.register_lbm({ + name = ":" .. mname .. ":start_nodetimer_" .. pname, + nodenames = lbm_nodes, + action = function(pos, node) + tick_again(pos) + end, + }) + + -- Return + local r = { + seed = mname .. ":seed_" .. pname, + harvest = mname .. ":" .. pname + } + return r +end diff --git a/mods/farming/depends.txt b/mods/farming/depends.txt new file mode 100644 index 0000000..301d971 --- /dev/null +++ b/mods/farming/depends.txt @@ -0,0 +1,3 @@ +default +wool +stairs diff --git a/mods/farming/hoes.lua b/mods/farming/hoes.lua new file mode 100644 index 0000000..3328582 --- /dev/null +++ b/mods/farming/hoes.lua @@ -0,0 +1,49 @@ +farming.register_hoe(":farming:hoe_wood", { + description = "Wooden Hoe", + inventory_image = "farming_tool_woodhoe.png", + max_uses = 30, + material = "group:wood", + groups = {flammable = 2, tool = 1}, +}) + +farming.register_hoe(":farming:hoe_stone", { + description = "Stone Hoe", + inventory_image = "farming_tool_stonehoe.png", + max_uses = 90, + material = "group:stone", + groups = {tool = 1}, +}) + +farming.register_hoe(":farming:hoe_steel", { + description = "Steel Hoe", + inventory_image = "farming_tool_steelhoe.png", + max_uses = 500, + material = "default:steel_ingot", + groups = {tool = 1}, +}) + +-- The following are deprecated by removing the 'material' field to prevent +-- crafting and removing from creative inventory, to cause them to eventually +-- disappear from worlds. The registrations should be removed in a future +-- release. + +farming.register_hoe(":farming:hoe_bronze", { + description = "Bronze Hoe", + inventory_image = "farming_tool_bronzehoe.png", + max_uses = 220, + groups = {not_in_creative_inventory = 1, tool = 1}, +}) + +farming.register_hoe(":farming:hoe_mese", { + description = "Mese Hoe", + inventory_image = "farming_tool_mesehoe.png", + max_uses = 350, + groups = {not_in_creative_inventory = 1, tool = 1}, +}) + +farming.register_hoe(":farming:hoe_diamond", { + description = "Diamond Hoe", + inventory_image = "farming_tool_diamondhoe.png", + max_uses = 500, + groups = {not_in_creative_inventory = 1, tool = 1}, +}) diff --git a/mods/farming/init.lua b/mods/farming/init.lua new file mode 100644 index 0000000..723201d --- /dev/null +++ b/mods/farming/init.lua @@ -0,0 +1,139 @@ +-- Global farming namespace + +farming = {} +farming.path = minetest.get_modpath("farming") + + +-- Load files + +dofile(farming.path .. "/api.lua") +dofile(farming.path .. "/nodes.lua") +dofile(farming.path .. "/hoes.lua") + + +-- WHEAT + +farming.register_plant("farming:wheat", { + description = "Wheat Seed", + paramtype2 = "meshoptions", + inventory_image = "farming_wheat_seed.png", + steps = 8, + minlight = 13, + maxlight = default.LIGHT_MAX, + fertility = {"grassland"}, + groups = {food_wheat = 1, flammable = 4}, + place_param2 = 3, +}) + +minetest.register_craftitem("farming:flour", { + description = "Flour", + inventory_image = "farming_flour.png", + groups = {food_flour = 1, flammable = 1}, +}) + +minetest.register_craftitem("farming:bread", { + description = "Bread", + inventory_image = "farming_bread.png", + on_use = minetest.item_eat(5), + groups = {food_bread = 1, flammable = 2}, +}) + +minetest.register_craft({ + type = "shapeless", + output = "farming:flour", + recipe = {"farming:wheat", "farming:wheat", "farming:wheat", "farming:wheat"} +}) + +minetest.register_craft({ + type = "cooking", + cooktime = 15, + output = "farming:bread", + recipe = "farming:flour" +}) + + +-- Cotton + +farming.register_plant("farming:cotton", { + description = "Cotton Seed", + inventory_image = "farming_cotton_seed.png", + steps = 8, + minlight = 13, + maxlight = default.LIGHT_MAX, + fertility = {"grassland", "desert"}, + groups = {flammable = 4}, +}) + +minetest.register_craftitem("farming:string", { + description = "String", + inventory_image = "farming_string.png", + groups = {flammable = 2}, +}) + +minetest.register_craft({ + output = "wool:white", + recipe = { + {"farming:cotton", "farming:cotton"}, + {"farming:cotton", "farming:cotton"}, + } +}) + +minetest.register_craft({ + output = "farming:string 2", + recipe = { + {"farming:cotton"}, + {"farming:cotton"}, + } +}) + + +-- Straw + +minetest.register_craft({ + output = "farming:straw 3", + recipe = { + {"farming:wheat", "farming:wheat", "farming:wheat"}, + {"farming:wheat", "farming:wheat", "farming:wheat"}, + {"farming:wheat", "farming:wheat", "farming:wheat"}, + } +}) + +minetest.register_craft({ + output = "farming:wheat 3", + recipe = { + {"farming:straw"}, + } +}) + + +-- Fuels + +minetest.register_craft({ + type = "fuel", + recipe = "farming:straw", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "farming:wheat", + burntime = 1, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "farming:cotton", + burntime = 1, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "farming:string", + burntime = 1, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "farming:hoe_wood", + burntime = 5, +}) diff --git a/mods/farming/license.txt b/mods/farming/license.txt new file mode 100644 index 0000000..8cbb63a --- /dev/null +++ b/mods/farming/license.txt @@ -0,0 +1,61 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 webdesigner97 +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +License of media (textures) +--------------------------- + +Attribution 3.0 Unported (CC BY 3.0) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2015-2016 MasterGollum +Copyright (C) 2015-2016 Gambit + +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. + +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/3.0/ diff --git a/mods/farming/nodes.lua b/mods/farming/nodes.lua new file mode 100644 index 0000000..cc9d1f6 --- /dev/null +++ b/mods/farming/nodes.lua @@ -0,0 +1,190 @@ +minetest.override_item("default:dirt", { + soil = { + base = "default:dirt", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.override_item("default:dirt_with_grass", { + soil = { + base = "default:dirt_with_grass", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.override_item("default:dirt_with_dry_grass", { + soil = { + base = "default:dirt_with_dry_grass", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.override_item("default:dirt_with_rainforest_litter", { + soil = { + base = "default:dirt_with_rainforest_litter", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.override_item("default:dirt_with_coniferous_litter", { + soil = { + base = "default:dirt_with_coniferous_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"}, + drop = "default:dirt", + groups = {crumbly=3, not_in_creative_inventory=1, soil=2, grassland = 1, field = 1}, + sounds = default.node_sound_dirt_defaults(), + soil = { + base = "default:dirt", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.register_node("farming:soil_wet", { + description = "Wet Soil", + tiles = {"default_dirt.png^farming_soil_wet.png", "default_dirt.png^farming_soil_wet_side.png"}, + drop = "default:dirt", + groups = {crumbly=3, not_in_creative_inventory=1, soil=3, wet = 1, grassland = 1, field = 1}, + sounds = default.node_sound_dirt_defaults(), + soil = { + base = "default:dirt", + dry = "farming:soil", + wet = "farming:soil_wet" + } +}) + +minetest.override_item("default:desert_sand", { + groups = {crumbly=3, falling_node=1, sand=1, soil = 1}, + soil = { + base = "default:desert_sand", + dry = "farming:desert_sand_soil", + wet = "farming:desert_sand_soil_wet" + } +}) +minetest.register_node("farming:desert_sand_soil", { + description = "Desert Sand Soil", + drop = "default:desert_sand", + tiles = {"farming_desert_sand_soil.png", "default_desert_sand.png"}, + groups = {crumbly=3, not_in_creative_inventory = 1, falling_node=1, sand=1, soil = 2, desert = 1, field = 1}, + sounds = default.node_sound_sand_defaults(), + soil = { + base = "default:desert_sand", + dry = "farming:desert_sand_soil", + wet = "farming:desert_sand_soil_wet" + } +}) + +minetest.register_node("farming:desert_sand_soil_wet", { + description = "Wet Desert Sand Soil", + drop = "default:desert_sand", + tiles = {"farming_desert_sand_soil_wet.png", "farming_desert_sand_soil_wet_side.png"}, + groups = {crumbly=3, falling_node=1, sand=1, not_in_creative_inventory=1, soil=3, wet = 1, desert = 1, field = 1}, + sounds = default.node_sound_sand_defaults(), + soil = { + base = "default:desert_sand", + dry = "farming:desert_sand_soil", + wet = "farming:desert_sand_soil_wet" + } +}) + +minetest.register_node("farming:straw", { + description = "Straw", + tiles = {"farming_straw.png"}, + is_ground_content = false, + groups = {snappy=3, flammable=4, fall_damage_add_percent=-30}, + sounds = default.node_sound_leaves_defaults(), +}) + +stairs.register_stair_and_slab( + "straw", + "farming:straw", + {snappy = 3, flammable = 4}, + {"farming_straw.png"}, + "Straw Stair", + "Straw Slab", + default.node_sound_leaves_defaults(), + true +) + +minetest.register_abm({ + label = "Farming soil", + nodenames = {"group:field"}, + interval = 15, + chance = 4, + action = function(pos, node) + local n_def = minetest.registered_nodes[node.name] or nil + local wet = n_def.soil.wet or nil + local base = n_def.soil.base or nil + local dry = n_def.soil.dry or nil + if not n_def or not n_def.soil or not wet or not base or not dry then + return + end + + pos.y = pos.y + 1 + local nn = minetest.get_node_or_nil(pos) + if not nn or not nn.name then + return + end + local nn_def = minetest.registered_nodes[nn.name] or nil + pos.y = pos.y - 1 + + if nn_def and nn_def.walkable and minetest.get_item_group(nn.name, "plant") == 0 then + minetest.set_node(pos, {name = base}) + return + end + -- check if there is water nearby + local wet_lvl = minetest.get_item_group(node.name, "wet") + if minetest.find_node_near(pos, 3, {"group:water"}) then + -- if it is dry soil and not base node, turn it into wet soil + if wet_lvl == 0 then + minetest.set_node(pos, {name = wet}) + end + else + -- only turn back if there are no unloaded blocks (and therefore + -- possible water sources) nearby + if not minetest.find_node_near(pos, 3, {"ignore"}) then + -- turn it back into base if it is already dry + if wet_lvl == 0 then + -- only turn it back if there is no plant/seed on top of it + if minetest.get_item_group(nn.name, "plant") == 0 and minetest.get_item_group(nn.name, "seed") == 0 then + minetest.set_node(pos, {name = base}) + end + + -- if its wet turn it back into dry soil + elseif wet_lvl == 1 then + minetest.set_node(pos, {name = dry}) + end + end + end + end, +}) + + +for i = 1, 5 do + minetest.override_item("default:grass_"..i, {drop = { + max_items = 1, + items = { + {items = {'farming:seed_wheat'},rarity = 5}, + {items = {'default:grass_1'}}, + } + }}) +end + +minetest.override_item("default:junglegrass", {drop = { + max_items = 1, + items = { + {items = {'farming:seed_cotton'},rarity = 8}, + {items = {'default:junglegrass'}}, + } +}}) diff --git a/mods/farming/textures/farming_bread.png b/mods/farming/textures/farming_bread.png new file mode 100644 index 0000000..0c25678 Binary files /dev/null and b/mods/farming/textures/farming_bread.png differ diff --git a/mods/farming/textures/farming_cotton.png b/mods/farming/textures/farming_cotton.png new file mode 100644 index 0000000..8aa50e4 Binary files /dev/null and b/mods/farming/textures/farming_cotton.png differ diff --git a/mods/farming/textures/farming_cotton_1.png b/mods/farming/textures/farming_cotton_1.png new file mode 100644 index 0000000..5fc2180 Binary files /dev/null and b/mods/farming/textures/farming_cotton_1.png differ diff --git a/mods/farming/textures/farming_cotton_2.png b/mods/farming/textures/farming_cotton_2.png new file mode 100644 index 0000000..db4f4a3 Binary files /dev/null and b/mods/farming/textures/farming_cotton_2.png differ diff --git a/mods/farming/textures/farming_cotton_3.png b/mods/farming/textures/farming_cotton_3.png new file mode 100644 index 0000000..df3d7a7 Binary files /dev/null and b/mods/farming/textures/farming_cotton_3.png differ diff --git a/mods/farming/textures/farming_cotton_4.png b/mods/farming/textures/farming_cotton_4.png new file mode 100644 index 0000000..f314b07 Binary files /dev/null and b/mods/farming/textures/farming_cotton_4.png differ diff --git a/mods/farming/textures/farming_cotton_5.png b/mods/farming/textures/farming_cotton_5.png new file mode 100644 index 0000000..3e89085 Binary files /dev/null and b/mods/farming/textures/farming_cotton_5.png differ diff --git a/mods/farming/textures/farming_cotton_6.png b/mods/farming/textures/farming_cotton_6.png new file mode 100644 index 0000000..f4bd4fb Binary files /dev/null and b/mods/farming/textures/farming_cotton_6.png differ diff --git a/mods/farming/textures/farming_cotton_7.png b/mods/farming/textures/farming_cotton_7.png new file mode 100644 index 0000000..466d40a Binary files /dev/null and b/mods/farming/textures/farming_cotton_7.png differ diff --git a/mods/farming/textures/farming_cotton_8.png b/mods/farming/textures/farming_cotton_8.png new file mode 100644 index 0000000..f835ba5 Binary files /dev/null and b/mods/farming/textures/farming_cotton_8.png differ diff --git a/mods/farming/textures/farming_cotton_seed.png b/mods/farming/textures/farming_cotton_seed.png new file mode 100644 index 0000000..f1d5b8a Binary files /dev/null and b/mods/farming/textures/farming_cotton_seed.png differ diff --git a/mods/farming/textures/farming_desert_sand_soil.png b/mods/farming/textures/farming_desert_sand_soil.png new file mode 100644 index 0000000..3c09ef0 Binary files /dev/null and b/mods/farming/textures/farming_desert_sand_soil.png differ diff --git a/mods/farming/textures/farming_desert_sand_soil_wet.png b/mods/farming/textures/farming_desert_sand_soil_wet.png new file mode 100644 index 0000000..facc83e Binary files /dev/null and b/mods/farming/textures/farming_desert_sand_soil_wet.png differ diff --git a/mods/farming/textures/farming_desert_sand_soil_wet_side.png b/mods/farming/textures/farming_desert_sand_soil_wet_side.png new file mode 100644 index 0000000..41e5a04 Binary files /dev/null and b/mods/farming/textures/farming_desert_sand_soil_wet_side.png differ diff --git a/mods/farming/textures/farming_flour.png b/mods/farming/textures/farming_flour.png new file mode 100644 index 0000000..b1a9783 Binary files /dev/null and b/mods/farming/textures/farming_flour.png differ diff --git a/mods/farming/textures/farming_soil.png b/mods/farming/textures/farming_soil.png new file mode 100644 index 0000000..5cd3e68 Binary files /dev/null and b/mods/farming/textures/farming_soil.png differ diff --git a/mods/farming/textures/farming_soil_wet.png b/mods/farming/textures/farming_soil_wet.png new file mode 100644 index 0000000..0b4487d Binary files /dev/null and b/mods/farming/textures/farming_soil_wet.png differ diff --git a/mods/farming/textures/farming_soil_wet_side.png b/mods/farming/textures/farming_soil_wet_side.png new file mode 100644 index 0000000..f0b1bd4 Binary files /dev/null and b/mods/farming/textures/farming_soil_wet_side.png differ diff --git a/mods/farming/textures/farming_straw.png b/mods/farming/textures/farming_straw.png new file mode 100644 index 0000000..f9f5fe7 Binary files /dev/null and b/mods/farming/textures/farming_straw.png differ diff --git a/mods/farming/textures/farming_string.png b/mods/farming/textures/farming_string.png new file mode 100644 index 0000000..e2bbfd7 Binary files /dev/null and b/mods/farming/textures/farming_string.png differ diff --git a/mods/farming/textures/farming_tool_bronzehoe.png b/mods/farming/textures/farming_tool_bronzehoe.png new file mode 100644 index 0000000..2802d11 Binary files /dev/null and b/mods/farming/textures/farming_tool_bronzehoe.png differ diff --git a/mods/farming/textures/farming_tool_diamondhoe.png b/mods/farming/textures/farming_tool_diamondhoe.png new file mode 100644 index 0000000..66f1042 Binary files /dev/null and b/mods/farming/textures/farming_tool_diamondhoe.png differ diff --git a/mods/farming/textures/farming_tool_mesehoe.png b/mods/farming/textures/farming_tool_mesehoe.png new file mode 100644 index 0000000..4534fba Binary files /dev/null and b/mods/farming/textures/farming_tool_mesehoe.png differ diff --git a/mods/farming/textures/farming_tool_steelhoe.png b/mods/farming/textures/farming_tool_steelhoe.png new file mode 100644 index 0000000..d057af2 Binary files /dev/null and b/mods/farming/textures/farming_tool_steelhoe.png differ diff --git a/mods/farming/textures/farming_tool_stonehoe.png b/mods/farming/textures/farming_tool_stonehoe.png new file mode 100644 index 0000000..55d8123 Binary files /dev/null and b/mods/farming/textures/farming_tool_stonehoe.png differ diff --git a/mods/farming/textures/farming_tool_woodhoe.png b/mods/farming/textures/farming_tool_woodhoe.png new file mode 100644 index 0000000..a287152 Binary files /dev/null and b/mods/farming/textures/farming_tool_woodhoe.png differ diff --git a/mods/farming/textures/farming_wheat.png b/mods/farming/textures/farming_wheat.png new file mode 100644 index 0000000..1e0ad3b Binary files /dev/null and b/mods/farming/textures/farming_wheat.png differ diff --git a/mods/farming/textures/farming_wheat_1.png b/mods/farming/textures/farming_wheat_1.png new file mode 100644 index 0000000..c16ad94 Binary files /dev/null and b/mods/farming/textures/farming_wheat_1.png differ diff --git a/mods/farming/textures/farming_wheat_2.png b/mods/farming/textures/farming_wheat_2.png new file mode 100644 index 0000000..baddb4c Binary files /dev/null and b/mods/farming/textures/farming_wheat_2.png differ diff --git a/mods/farming/textures/farming_wheat_3.png b/mods/farming/textures/farming_wheat_3.png new file mode 100644 index 0000000..36ebb19 Binary files /dev/null and b/mods/farming/textures/farming_wheat_3.png differ diff --git a/mods/farming/textures/farming_wheat_4.png b/mods/farming/textures/farming_wheat_4.png new file mode 100644 index 0000000..735ed77 Binary files /dev/null and b/mods/farming/textures/farming_wheat_4.png differ diff --git a/mods/farming/textures/farming_wheat_5.png b/mods/farming/textures/farming_wheat_5.png new file mode 100644 index 0000000..f40b5f0 Binary files /dev/null and b/mods/farming/textures/farming_wheat_5.png differ diff --git a/mods/farming/textures/farming_wheat_6.png b/mods/farming/textures/farming_wheat_6.png new file mode 100644 index 0000000..e9c78e0 Binary files /dev/null and b/mods/farming/textures/farming_wheat_6.png differ diff --git a/mods/farming/textures/farming_wheat_7.png b/mods/farming/textures/farming_wheat_7.png new file mode 100644 index 0000000..cc26ca9 Binary files /dev/null and b/mods/farming/textures/farming_wheat_7.png differ diff --git a/mods/farming/textures/farming_wheat_8.png b/mods/farming/textures/farming_wheat_8.png new file mode 100644 index 0000000..d050093 Binary files /dev/null and b/mods/farming/textures/farming_wheat_8.png differ diff --git a/mods/farming/textures/farming_wheat_seed.png b/mods/farming/textures/farming_wheat_seed.png new file mode 100644 index 0000000..a9031fb Binary files /dev/null and b/mods/farming/textures/farming_wheat_seed.png differ diff --git a/mods/fire/README.txt b/mods/fire/README.txt new file mode 100644 index 0000000..25ba26e --- /dev/null +++ b/mods/fire/README.txt @@ -0,0 +1,35 @@ +Minetest Game mod: fire +======================= +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Perttu Ahola (celeron55) (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures and sounds) +-------------------------------------- +Everything not listed in here: +Copyright (C) 2012 Perttu Ahola (celeron55) (CC BY-SA 3.0) + +Muadtralk (CC BY-SA 3.0) + fire_basic_flame_animated.png + +Gambit (CC BY-SA 3.0) + fire_flint_steel.png + +dobroide (CC BY 3.0) +http://www.freesound.org/people/dobroide/sounds/4211/ + fire_small.ogg + +Dynamicell (CC BY 3.0) +http://www.freesound.org/people/Dynamicell/sounds/17548/ + fire_large.ogg + fire_fire.*.ogg + +fire_small.ogg and fire_large.ogg are unused but kept temporarily to not break +other mods that may use them. + +Benboncan (CC BY 3.0) +https://www.freesound.org/people/Benboncan/sounds/66457/ + fire_flint_and_steel.ogg diff --git a/mods/fire/depends.txt b/mods/fire/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/fire/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/fire/init.lua b/mods/fire/init.lua new file mode 100644 index 0000000..612e052 --- /dev/null +++ b/mods/fire/init.lua @@ -0,0 +1,355 @@ +-- Global namespace for functions + +fire = {} + +-- 'Enable fire' setting + +local fire_enabled = minetest.settings:get_bool("enable_fire") +if fire_enabled == nil then + -- 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 + +-- +-- Items +-- + +-- Flood flame function + +local function flood_flame(pos, oldnode, newnode) + -- Play flame extinguish sound if liquid is not an 'igniter' + local nodedef = minetest.registered_items[newnode.name] + if not (nodedef and nodedef.groups and + nodedef.groups.igniter and nodedef.groups.igniter > 0) then + minetest.sound_play("fire_extinguish_flame", + {pos = pos, max_hear_distance = 16, gain = 0.15}) + end + -- Remove the flame + return false +end + +-- Flame nodes + +minetest.register_node("fire:basic_flame", { + drawtype = "firelike", + tiles = { + { + name = "fire_basic_flame_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1 + }, + }, + }, + inventory_image = "fire_basic_flame.png", + paramtype = "light", + light_source = 13, + walkable = false, + buildable_to = true, + sunlight_propagates = true, + floodable = true, + damage_per_second = 4, + groups = {igniter = 2, dig_immediate = 3, not_in_creative_inventory = 1}, + drop = "", + + on_timer = function(pos) + local f = minetest.find_node_near(pos, 1, {"group:flammable"}) + if not fire_enabled or not f then + minetest.remove_node(pos) + return + end + -- Restart timer + return true + end, + + on_construct = function(pos) + if not fire_enabled then + minetest.remove_node(pos) + else + minetest.get_node_timer(pos):start(math.random(30, 60)) + end + end, + + on_flood = flood_flame, +}) + +minetest.register_node("fire:permanent_flame", { + description = "Permanent Flame", + drawtype = "firelike", + tiles = { + { + name = "fire_basic_flame_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1 + }, + }, + }, + inventory_image = "fire_basic_flame.png", + paramtype = "light", + light_source = 13, + walkable = false, + buildable_to = true, + sunlight_propagates = true, + floodable = true, + damage_per_second = 4, + groups = {igniter = 2, dig_immediate = 3}, + drop = "", + + on_flood = flood_flame, +}) + + +-- Flint and steel + +minetest.register_tool("fire:flint_and_steel", { + description = "Flint and Steel", + inventory_image = "fire_flint_steel.png", + sound = {breaks = "default_tool_breaks"}, + + on_use = function(itemstack, user, pointed_thing) + local sound_pos = pointed_thing.above or user:get_pos() + minetest.sound_play( + "fire_flint_and_steel", + {pos = sound_pos, gain = 0.5, max_hear_distance = 8} + ) + 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 + 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(pointed_thing.under, user) + elseif minetest.get_item_group(node_under, "flammable") >= 1 + and minetest.get_node(pointed_thing.above).name == "air" then + minetest.set_node(pointed_thing.above, {name = "fire:basic_flame"}) + end + end + 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 = sound_pos, gain = 0.5}) + end + return itemstack + end + end +}) + +minetest.register_craft({ + output = "fire:flint_and_steel", + recipe = { + {"default:flint", "default:steel_ingot"} + } +}) + + +-- Override coalblock to enable permanent flame above +-- Coalblock is non-flammable to avoid unwanted basic_flame nodes + +minetest.override_item("default:coalblock", { + after_destruct = function(pos, oldnode) + pos.y = pos.y + 1 + if minetest.get_node(pos).name == "fire:permanent_flame" then + minetest.remove_node(pos) + end + end, + on_ignite = function(pos, igniter) + local flame_pos = {x = pos.x, y = pos.y + 1, z = pos.z} + if minetest.get_node(flame_pos).name == "air" then + minetest.set_node(flame_pos, {name = "fire:permanent_flame"}) + end + end, +}) + + +-- +-- Sound +-- + +local flame_sound = minetest.settings:get_bool("flame_sound") +if flame_sound == nil then + -- Enable if no setting present + flame_sound = true +end + +if flame_sound then + + local handles = {} + local timer = 0 + + -- Parameters + + local radius = 8 -- Flame node search radius around player + local cycle = 3 -- Cycle time for sound updates + + -- Update sound for player + + function fire.update_player_sound(player) + local player_name = player:get_player_name() + -- Search for flame nodes in radius around player + local ppos = player:get_pos() + local areamin = vector.subtract(ppos, radius) + local areamax = vector.add(ppos, radius) + local fpos, num = minetest.find_nodes_in_area( + areamin, + areamax, + {"fire:basic_flame", "fire:permanent_flame"} + ) + -- Total number of flames in radius + local flames = (num["fire:basic_flame"] or 0) + + (num["fire:permanent_flame"] or 0) + -- Stop previous sound + if handles[player_name] then + minetest.sound_stop(handles[player_name]) + handles[player_name] = nil + end + -- If flames + if flames > 0 then + -- Find centre of flame positions + local fposmid = fpos[1] + -- If more than 1 flame + if #fpos > 1 then + local fposmin = areamax + local fposmax = areamin + for i = 1, #fpos do + local fposi = fpos[i] + if fposi.x > fposmax.x then + fposmax.x = fposi.x + end + if fposi.y > fposmax.y then + fposmax.y = fposi.y + end + if fposi.z > fposmax.z then + fposmax.z = fposi.z + end + if fposi.x < fposmin.x then + fposmin.x = fposi.x + end + if fposi.y < fposmin.y then + fposmin.y = fposi.y + end + if fposi.z < fposmin.z then + fposmin.z = fposi.z + end + end + fposmid = vector.divide(vector.add(fposmin, fposmax), 2) + end + -- Play sound + local handle = minetest.sound_play( + "fire_fire", + { + pos = fposmid, + to_player = player_name, + gain = math.min(0.06 * (1 + flames * 0.125), 0.18), + max_hear_distance = 32, + loop = true, -- In case of lag + } + ) + -- Store sound handle for this player + if handle then + handles[player_name] = handle + end + end + end + + -- Cycle for updating players sounds + + minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer < cycle then + return + end + + timer = 0 + local players = minetest.get_connected_players() + for n = 1, #players do + fire.update_player_sound(players[n]) + end + end) + + -- Stop sound and clear handle on player leave + + minetest.register_on_leaveplayer(function(player) + local player_name = player:get_player_name() + if handles[player_name] then + minetest.sound_stop(handles[player_name]) + handles[player_name] = nil + end + end) +end + + +-- Deprecated function kept temporarily to avoid crashes if mod fire nodes call it + +function fire.update_sounds_around(pos) +end + + +-- +-- ABMs +-- + +if fire_enabled then + + -- Ignite neighboring nodes, add basic flames + + minetest.register_abm({ + label = "Ignite flame", + nodenames = {"group:flammable"}, + neighbors = {"group:igniter"}, + interval = 7, + chance = 12, + catch_up = false, + action = function(pos, node, active_object_count, active_object_count_wider) + local p = minetest.find_node_near(pos, 1, {"air"}) + if p then + minetest.set_node(p, {name = "fire:basic_flame"}) + end + end, + }) + + -- Remove flammable nodes around basic flame + + minetest.register_abm({ + label = "Remove flammable nodes", + nodenames = {"fire:basic_flame"}, + neighbors = "group:flammable", + interval = 5, + chance = 18, + catch_up = false, + action = function(pos, node, active_object_count, active_object_count_wider) + local p = minetest.find_node_near(pos, 1, {"group:flammable"}) + if p then + local flammable_node = minetest.get_node(p) + local def = minetest.registered_nodes[flammable_node.name] + if def.on_burn then + def.on_burn(p) + else + minetest.remove_node(p) + minetest.check_for_falling(p) + end + end + end, + }) + +end diff --git a/mods/fire/license.txt b/mods/fire/license.txt new file mode 100644 index 0000000..43f9cd7 --- /dev/null +++ b/mods/fire/license.txt @@ -0,0 +1,84 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2012-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 and sounds) +--------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) +Copyright (C) 2012-2016 Muadtralk +Copyright (C) 2013-2016 Gambit + +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/ + +----------------------- + +Attribution 3.0 Unported (CC BY 3.0) +Copyright (C) 2005 dobroide +Copyright (C) 2006 Dynamicell +Copyright (C) 2009 Benboncan + +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. + +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/3.0/ diff --git a/mods/fire/sounds/fire_extinguish_flame.1.ogg b/mods/fire/sounds/fire_extinguish_flame.1.ogg new file mode 100644 index 0000000..42506dd Binary files /dev/null and b/mods/fire/sounds/fire_extinguish_flame.1.ogg differ diff --git a/mods/fire/sounds/fire_extinguish_flame.2.ogg b/mods/fire/sounds/fire_extinguish_flame.2.ogg new file mode 100644 index 0000000..2747ab8 Binary files /dev/null and b/mods/fire/sounds/fire_extinguish_flame.2.ogg differ diff --git a/mods/fire/sounds/fire_extinguish_flame.3.ogg b/mods/fire/sounds/fire_extinguish_flame.3.ogg new file mode 100644 index 0000000..8baeac3 Binary files /dev/null and b/mods/fire/sounds/fire_extinguish_flame.3.ogg differ diff --git a/mods/fire/sounds/fire_fire.1.ogg b/mods/fire/sounds/fire_fire.1.ogg new file mode 100644 index 0000000..cbfee4c Binary files /dev/null and b/mods/fire/sounds/fire_fire.1.ogg differ diff --git a/mods/fire/sounds/fire_fire.2.ogg b/mods/fire/sounds/fire_fire.2.ogg new file mode 100644 index 0000000..e8d0eb1 Binary files /dev/null and b/mods/fire/sounds/fire_fire.2.ogg differ diff --git a/mods/fire/sounds/fire_fire.3.ogg b/mods/fire/sounds/fire_fire.3.ogg new file mode 100644 index 0000000..5cad3d9 Binary files /dev/null and b/mods/fire/sounds/fire_fire.3.ogg differ diff --git a/mods/fire/sounds/fire_flint_and_steel.ogg b/mods/fire/sounds/fire_flint_and_steel.ogg new file mode 100644 index 0000000..6996e16 Binary files /dev/null and b/mods/fire/sounds/fire_flint_and_steel.ogg differ diff --git a/mods/fire/sounds/fire_large.ogg b/mods/fire/sounds/fire_large.ogg new file mode 100644 index 0000000..fe78e62 Binary files /dev/null and b/mods/fire/sounds/fire_large.ogg differ diff --git a/mods/fire/sounds/fire_small.ogg b/mods/fire/sounds/fire_small.ogg new file mode 100644 index 0000000..5aac595 Binary files /dev/null and b/mods/fire/sounds/fire_small.ogg differ diff --git a/mods/fire/textures/fire_basic_flame.png b/mods/fire/textures/fire_basic_flame.png new file mode 100644 index 0000000..1da0702 Binary files /dev/null and b/mods/fire/textures/fire_basic_flame.png differ diff --git a/mods/fire/textures/fire_basic_flame_animated.png b/mods/fire/textures/fire_basic_flame_animated.png new file mode 100644 index 0000000..1cdd9fd Binary files /dev/null and b/mods/fire/textures/fire_basic_flame_animated.png differ diff --git a/mods/fire/textures/fire_flint_steel.png b/mods/fire/textures/fire_flint_steel.png new file mode 100644 index 0000000..c262ebc Binary files /dev/null and b/mods/fire/textures/fire_flint_steel.png differ diff --git a/mods/fireflies/README.txt b/mods/fireflies/README.txt new file mode 100644 index 0000000..7382578 --- /dev/null +++ b/mods/fireflies/README.txt @@ -0,0 +1,22 @@ +Minetest Game mod: fireflies +============================ +Adds fireflies to the world on mapgen, which can then be caught in a net and placed in +bottles to provide light. + +Authors of source code +---------------------- +Shara RedCat (MIT) + +Authors of media (textures) +--------------------------- +Shara RedCat (CC BY-SA 3.0): + fireflies_firefly.png + fireflies_firefly_animated.png + fireflies_bugnet.png + fireflies_bottle.png + fireflies_bottle_animated.png + +fireflies_bugnet.png is modified from a texture by tenplus1 (CC0) + +fireflies_bottle.png and fireflies_bottle_animated.png are +modified from a texture by Vanessa Ezekowitz (CC BY-SA 3.0) \ No newline at end of file diff --git a/mods/fireflies/depends.txt b/mods/fireflies/depends.txt new file mode 100644 index 0000000..e0585b4 --- /dev/null +++ b/mods/fireflies/depends.txt @@ -0,0 +1,2 @@ +default +vessels \ No newline at end of file diff --git a/mods/fireflies/init.lua b/mods/fireflies/init.lua new file mode 100644 index 0000000..3910787 --- /dev/null +++ b/mods/fireflies/init.lua @@ -0,0 +1,287 @@ +-- firefly +minetest.register_node("fireflies:firefly", { + description = "Firefly", + drawtype = "plantlike", + tiles = {{ + name = "fireflies_firefly_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.5 + }, + }}, + inventory_image = "fireflies_firefly.png", + wield_image = "fireflies_firefly.png", + waving = 1, + paramtype = "light", + sunlight_propagates = true, + buildable_to = true, + walkable = false, + groups = {catchable = 1}, + selection_box = { + type = "fixed", + fixed = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1}, + }, + light_source = 6, + floodable = true, + on_place = function(itemstack, placer, pointed_thing) + local player_name = placer:get_player_name() + local pos = pointed_thing.above + + if not minetest.is_protected(pos, player_name) and + not minetest.is_protected(pointed_thing.under, player_name) and + minetest.get_node(pos).name == "air" then + minetest.set_node(pos, {name = "fireflies:firefly"}) + minetest.get_node_timer(pos):start(1) + itemstack:take_item() + end + return itemstack + end, + on_timer = function(pos, elapsed) + if minetest.get_node_light(pos) > 11 then + minetest.set_node(pos, {name = "fireflies:hidden_firefly"}) + end + minetest.get_node_timer(pos):start(30) + end +}) + +minetest.register_node("fireflies:hidden_firefly", { + description = "Hidden Firefly", + drawtype = "airlike", + inventory_image = "fireflies_firefly.png", + wield_image = "fireflies_firefly.png", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + drop = "", + groups = {not_in_creative_inventory = 1}, + floodable = true, + on_place = function(itemstack, placer, pointed_thing) + local player_name = placer:get_player_name() + local pos = pointed_thing.above + + if not minetest.is_protected(pos, player_name) and + not minetest.is_protected(pointed_thing.under, player_name) and + minetest.get_node(pos).name == "air" then + minetest.set_node(pos, {name = "fireflies:hidden_firefly"}) + minetest.get_node_timer(pos):start(1) + itemstack:take_item() + end + return itemstack + end, + on_timer = function(pos, elapsed) + if minetest.get_node_light(pos) <= 11 then + minetest.set_node(pos, {name = "fireflies:firefly"}) + end + minetest.get_node_timer(pos):start(30) + end +}) + + +-- bug net +minetest.register_tool("fireflies:bug_net", { + description = "Net\nRight-click for mobs\nLeft-click for bugs", + inventory_image = "fireflies_bugnet.png", + groups = {tool = 1}, + on_use = function(itemstack, player, pointed_thing) + if not pointed_thing or pointed_thing.type ~= "node" or + minetest.is_protected(pointed_thing.under, player:get_player_name()) then + return + end + local node_name = minetest.get_node(pointed_thing.under).name + local inv = player:get_inventory() + if minetest.get_item_group(node_name, "catchable") == 1 then + minetest.set_node(pointed_thing.under, {name = "air"}) + local stack = ItemStack(node_name.." 1") + local leftover = inv:add_item("main", stack) + if leftover:get_count() > 0 then + minetest.add_item(pointed_thing.under, node_name.." 1") + end + end + if not (creative and creative.is_enabled_for(player:get_player_name())) then + itemstack:add_wear(256) + return itemstack + end + end +}) + +minetest.register_craft( { + output = "fireflies:bug_net", + recipe = { + {"farming:string", "farming:string", ""}, + {"farming:string", "farming:string", ""}, + {"default:stick", "", ""} + } +}) + + +-- firefly in a bottle +minetest.register_node("fireflies:firefly_bottle", { + description = "Firefly in a Bottle", + inventory_image = "fireflies_bottle.png", + wield_image = "fireflies_bottle.png", + tiles = {{ + name = "fireflies_bottle_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1.5 + }, + }}, + drawtype = "plantlike", + paramtype = "light", + sunlight_propagates = true, + light_source = 9, + walkable = false, + groups = {dig_immediate = 3, attached_node = 1}, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + sounds = default.node_sound_glass_defaults(), + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + local lower_pos = {x = pos.x, y = pos.y + 1, z = pos.z} + if minetest.is_protected(pos, player:get_player_name()) or + minetest.get_node(lower_pos).name ~= "air" then + return + end + + local upper_pos = {x = pos.x, y = pos.y + 2, z = pos.z} + local firefly_pos + + if not minetest.is_protected(upper_pos, player:get_player_name()) and + minetest.get_node(upper_pos).name == "air" then + firefly_pos = upper_pos + elseif not minetest.is_protected(lower_pos, player:get_player_name()) then + firefly_pos = lower_pos + end + + if firefly_pos then + minetest.set_node(pos, {name = "vessels:glass_bottle"}) + minetest.set_node(firefly_pos, {name = "fireflies:firefly"}) + minetest.get_node_timer(firefly_pos):start(1) + end + end +}) + +minetest.register_craft( { + output = "fireflies:firefly_bottle", + recipe = { + {"", "", ""}, + {"", "fireflies:firefly", ""}, + {"", "vessels:glass_bottle", ""} + } +}) + + +-- register fireflies as decorations + +if minetest.get_mapgen_setting("mg_name") == "v6" then + + minetest.register_decoration({ + name = "fireflies:firefly_low", + deco_type = "simple", + place_on = "default:dirt_with_grass", + place_offset_y = 2, + sidelen = 80, + fill_ratio = 0.0002, + y_max = 31000, + y_min = 1, + decoration = "fireflies:hidden_firefly", + }) + + minetest.register_decoration({ + name = "fireflies:firefly_high", + deco_type = "simple", + place_on = "default:dirt_with_grass", + place_offset_y = 3, + sidelen = 80, + fill_ratio = 0.0002, + y_max = 31000, + y_min = 1, + decoration = "fireflies:hidden_firefly", + }) + +else + + minetest.register_decoration({ + name = "fireflies:firefly_low", + deco_type = "simple", + place_on = { + "default:dirt_with_grass", + "default:dirt_with_coniferous_litter", + "default:dirt_with_rainforest_litter", + "default:dirt" + }, + place_offset_y = 2, + sidelen = 80, + fill_ratio = 0.0005, + biomes = { + "deciduous_forest", + "coniferous_forest", + "rainforest", + "rainforest_swamp" + }, + y_max = 31000, + y_min = -1, + decoration = "fireflies:hidden_firefly", + }) + + minetest.register_decoration({ + name = "fireflies:firefly_high", + deco_type = "simple", + place_on = { + "default:dirt_with_grass", + "default:dirt_with_coniferous_litter", + "default:dirt_with_rainforest_litter", + "default:dirt" + }, + place_offset_y = 3, + sidelen = 80, + fill_ratio = 0.0005, + biomes = { + "deciduous_forest", + "coniferous_forest", + "rainforest", + "rainforest_swamp" + }, + y_max = 31000, + y_min = -1, + decoration = "fireflies:hidden_firefly", + }) + +end + + +-- get decoration IDs +local firefly_low = minetest.get_decoration_id("fireflies:firefly_low") +local firefly_high = minetest.get_decoration_id("fireflies:firefly_high") + +minetest.set_gen_notify({decoration = true}, {firefly_low, firefly_high}) + +-- start nodetimers +minetest.register_on_generated(function(minp, maxp, blockseed) + local gennotify = minetest.get_mapgen_object("gennotify") + local poslist = {} + + for _, pos in ipairs(gennotify["decoration#"..firefly_low] or {}) do + local firefly_low_pos = {x = pos.x, y = pos.y + 3, z = pos.z} + table.insert(poslist, firefly_low_pos) + end + for _, pos in ipairs(gennotify["decoration#"..firefly_high] or {}) do + local firefly_high_pos = {x = pos.x, y = pos.y + 4, z = pos.z} + table.insert(poslist, firefly_high_pos) + end + + if #poslist ~= 0 then + for i = 1, #poslist do + local pos = poslist[i] + minetest.get_node_timer(pos):start(1) + end + end +end) diff --git a/mods/fireflies/license.txt b/mods/fireflies/license.txt new file mode 100644 index 0000000..eebdad6 --- /dev/null +++ b/mods/fireflies/license.txt @@ -0,0 +1,58 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (c) 2018 Shara RedCat + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2018 Shara RedCat + +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/ \ No newline at end of file diff --git a/mods/fireflies/textures/fireflies_bottle.png b/mods/fireflies/textures/fireflies_bottle.png new file mode 100644 index 0000000..ecca036 Binary files /dev/null and b/mods/fireflies/textures/fireflies_bottle.png differ diff --git a/mods/fireflies/textures/fireflies_bottle_animated.png b/mods/fireflies/textures/fireflies_bottle_animated.png new file mode 100644 index 0000000..96062b3 Binary files /dev/null and b/mods/fireflies/textures/fireflies_bottle_animated.png differ diff --git a/mods/fireflies/textures/fireflies_bugnet.png b/mods/fireflies/textures/fireflies_bugnet.png new file mode 100644 index 0000000..8ec3d33 Binary files /dev/null and b/mods/fireflies/textures/fireflies_bugnet.png differ diff --git a/mods/fireflies/textures/fireflies_firefly.png b/mods/fireflies/textures/fireflies_firefly.png new file mode 100644 index 0000000..c086689 Binary files /dev/null and b/mods/fireflies/textures/fireflies_firefly.png differ diff --git a/mods/fireflies/textures/fireflies_firefly_animated.png b/mods/fireflies/textures/fireflies_firefly_animated.png new file mode 100644 index 0000000..e6932e3 Binary files /dev/null and b/mods/fireflies/textures/fireflies_firefly_animated.png differ diff --git a/mods/flowers/README.txt b/mods/flowers/README.txt new file mode 100644 index 0000000..4b3149c --- /dev/null +++ b/mods/flowers/README.txt @@ -0,0 +1,30 @@ +Minetest Game mod: flowers +========================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Ironzorg (MIT) and VanessaE (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +RHRhino (CC BY-SA 3.0): + flowers_dandelion_white.png + flowers_geranium.png + flowers_rose.png + flowers_tulip.png + flowers_viola.png + +Gambit (CC BY-SA 3.0): + flowers_mushroom_brown.png + flowers_mushroom_red.png + flowers_waterlily.png + +yyt16384 (CC BY-SA 3.0): + flowers_waterlily_bottom.png -- Derived from Gambit's texture + +paramat (CC BY-SA 3.0): + flowers_dandelion_yellow.png -- Derived from RHRhino's texture + flowers_tulip_black.png -- Derived from RHRhino's texture + flowers_chrysanthemum_green.png diff --git a/mods/flowers/depends.txt b/mods/flowers/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/flowers/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/flowers/init.lua b/mods/flowers/init.lua new file mode 100644 index 0000000..3ad4bf6 --- /dev/null +++ b/mods/flowers/init.lua @@ -0,0 +1,321 @@ +-- Minetest 0.4 mod: default +-- See README.txt for licensing and other information. + + +-- Namespace for functions + +flowers = {} + + +-- Map Generation + +dofile(minetest.get_modpath("flowers") .. "/mapgen.lua") + + +-- +-- Flowers +-- + +-- Aliases for original flowers mod + +minetest.register_alias("flowers:flower_rose", "flowers:rose") +minetest.register_alias("flowers:flower_tulip", "flowers:tulip") +minetest.register_alias("flowers:flower_dandelion_yellow", "flowers:dandelion_yellow") +minetest.register_alias("flowers:flower_geranium", "flowers:geranium") +minetest.register_alias("flowers:flower_viola", "flowers:viola") +minetest.register_alias("flowers:flower_dandelion_white", "flowers:dandelion_white") + + +-- Flower registration + +local function add_simple_flower(name, desc, box, f_groups) + -- Common flowers' groups + f_groups.snappy = 3 + f_groups.flower = 1 + f_groups.flora = 1 + f_groups.attached_node = 1 + + minetest.register_node("flowers:" .. name, { + description = desc, + drawtype = "plantlike", + waving = 1, + tiles = {"flowers_" .. name .. ".png"}, + inventory_image = "flowers_" .. name .. ".png", + wield_image = "flowers_" .. name .. ".png", + sunlight_propagates = true, + paramtype = "light", + walkable = false, + buildable_to = true, + stack_max = 99, + groups = f_groups, + sounds = default.node_sound_leaves_defaults(), + selection_box = { + type = "fixed", + fixed = box + } + }) +end + +flowers.datas = { + { + "rose", + "Red Rose", + {-2 / 16, -0.5, -2 / 16, 2 / 16, 5 / 16, 2 / 16}, + {color_red = 1, flammable = 1} + }, + { + "tulip", + "Orange Tulip", + {-2 / 16, -0.5, -2 / 16, 2 / 16, 3 / 16, 2 / 16}, + {color_orange = 1, flammable = 1} + }, + { + "dandelion_yellow", + "Yellow Dandelion", + {-4 / 16, -0.5, -4 / 16, 4 / 16, -2 / 16, 4 / 16}, + {color_yellow = 1, flammable = 1} + }, + { + "chrysanthemum_green", + "Green Chrysanthemum", + {-4 / 16, -0.5, -4 / 16, 4 / 16, -1 / 16, 4 / 16}, + {color_green = 1, flammable = 1} + }, + { + "geranium", + "Blue Geranium", + {-2 / 16, -0.5, -2 / 16, 2 / 16, 2 / 16, 2 / 16}, + {color_blue = 1, flammable = 1} + }, + { + "viola", + "Viola", + {-5 / 16, -0.5, -5 / 16, 5 / 16, -1 / 16, 5 / 16}, + {color_violet = 1, flammable = 1} + }, + { + "dandelion_white", + "White Dandelion", + {-5 / 16, -0.5, -5 / 16, 5 / 16, -2 / 16, 5 / 16}, + {color_white = 1, flammable = 1} + }, + { + "tulip_black", + "Black Tulip", + {-2 / 16, -0.5, -2 / 16, 2 / 16, 3 / 16, 2 / 16}, + {color_black = 1, flammable = 1} + }, +} + +for _,item in pairs(flowers.datas) do + add_simple_flower(unpack(item)) +end + + +-- Flower spread +-- Public function to enable override by mods + +function flowers.flower_spread(pos, node) + pos.y = pos.y - 1 + local under = minetest.get_node(pos) + pos.y = pos.y + 1 + -- 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 + end + + if minetest.get_item_group(under.name, "soil") == 0 then + return + end + + local light = minetest.get_node_light(pos) + if not light or light < 13 then + return + end + + local pos0 = vector.subtract(pos, 4) + local pos1 = vector.add(pos, 4) + -- Testing shows that a threshold of 3 results in an appropriate maximum + -- density of approximately 7 flora per 9x9 area. + if #minetest.find_nodes_in_area(pos0, pos1, "group:flora") > 3 then + return + end + + local soils = minetest.find_nodes_in_area_under_air( + pos0, pos1, "group:soil") + local num_soils = #soils + if num_soils >= 1 then + for si = 1, math.min(3, num_soils) do + local soil = soils[math.random(num_soils)] + local soil_name = minetest.get_node(soil).name + local soil_above = {x = soil.x, y = soil.y + 1, z = soil.z} + light = minetest.get_node_light(soil_above) + if light and light >= 13 and + -- Only spread to same surface node + soil_name == under.name and + -- Desert sand is in the soil group + soil_name ~= "default:desert_sand" then + minetest.set_node(soil_above, {name = node.name}) + end + end + end +end + +minetest.register_abm({ + label = "Flower spread", + nodenames = {"group:flora"}, + interval = 13, + chance = 300, + action = function(...) + flowers.flower_spread(...) + end, +}) + + +-- +-- Mushrooms +-- + +minetest.register_node("flowers:mushroom_red", { + description = "Red Mushroom", + tiles = {"flowers_mushroom_red.png"}, + inventory_image = "flowers_mushroom_red.png", + wield_image = "flowers_mushroom_red.png", + drawtype = "plantlike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {snappy = 3, attached_node = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + on_use = minetest.item_eat(-5), + selection_box = { + type = "fixed", + fixed = {-4 / 16, -0.5, -4 / 16, 4 / 16, -1 / 16, 4 / 16}, + } +}) + +minetest.register_node("flowers:mushroom_brown", { + description = "Brown Mushroom", + tiles = {"flowers_mushroom_brown.png"}, + inventory_image = "flowers_mushroom_brown.png", + wield_image = "flowers_mushroom_brown.png", + drawtype = "plantlike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + buildable_to = true, + groups = {food_mushroom = 1, snappy = 3, attached_node = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + on_use = minetest.item_eat(1), + selection_box = { + type = "fixed", + fixed = {-3 / 16, -0.5, -3 / 16, 3 / 16, -2 / 16, 3 / 16}, + } +}) + + +-- Mushroom spread and death + +function flowers.mushroom_spread(pos, node) + if minetest.get_node_light(pos, nil) == 15 then + minetest.remove_node(pos) + return + end + local positions = minetest.find_nodes_in_area_under_air( + {x = pos.x - 1, y = pos.y - 2, z = pos.z - 1}, + {x = pos.x + 1, y = pos.y + 1, z = pos.z + 1}, + {"group:soil", "group:tree"}) + if #positions == 0 then + return + end + local pos2 = positions[math.random(#positions)] + pos2.y = pos2.y + 1 + if minetest.get_node_light(pos, 0.5) <= 3 and + minetest.get_node_light(pos2, 0.5) <= 3 then + minetest.set_node(pos2, {name = node.name}) + end +end + +minetest.register_abm({ + label = "Mushroom spread", + nodenames = {"flowers:mushroom_brown", "flowers:mushroom_red"}, + interval = 11, + chance = 150, + action = function(...) + flowers.mushroom_spread(...) + end, +}) + + +-- These old mushroom related nodes can be simplified now + +minetest.register_alias("flowers:mushroom_spores_brown", "flowers:mushroom_brown") +minetest.register_alias("flowers:mushroom_spores_red", "flowers:mushroom_red") +minetest.register_alias("flowers:mushroom_fertile_brown", "flowers:mushroom_brown") +minetest.register_alias("flowers:mushroom_fertile_red", "flowers:mushroom_red") +minetest.register_alias("mushroom:brown_natural", "flowers:mushroom_brown") +minetest.register_alias("mushroom:red_natural", "flowers:mushroom_red") + + +-- +-- Waterlily +-- + +minetest.register_node("flowers:waterlily", { + description = "Waterlily", + drawtype = "nodebox", + paramtype = "light", + paramtype2 = "facedir", + tiles = {"flowers_waterlily.png", "flowers_waterlily_bottom.png"}, + inventory_image = "flowers_waterlily.png", + wield_image = "flowers_waterlily.png", + liquids_pointable = true, + walkable = false, + buildable_to = true, + floodable = true, + groups = {snappy = 3, flower = 1, flammable = 1}, + sounds = default.node_sound_leaves_defaults(), + node_placement_prediction = "", + node_box = { + type = "fixed", + fixed = {-0.5, -31 / 64, -0.5, 0.5, -15 / 32, 0.5} + }, + selection_box = { + type = "fixed", + fixed = {-7 / 16, -0.5, -7 / 16, 7 / 16, -15 / 32, 7 / 16} + }, + + on_place = function(itemstack, placer, pointed_thing) + local pos = pointed_thing.above + local node = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[node.name] + local player_name = placer and placer:get_player_name() or "" + + if def and def.on_rightclick then + return def.on_rightclick(pointed_thing.under, node, placer, itemstack, + pointed_thing) + end + + if def and def.liquidtype == "source" and + minetest.get_item_group(node.name, "water") > 0 then + if not minetest.is_protected(pos, player_name) then + minetest.set_node(pos, {name = "flowers:waterlily", + param2 = math.random(0, 3)}) + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) then + itemstack:take_item() + end + else + minetest.chat_send_player(player_name, "Node is protected") + minetest.record_protection_violation(pos, player_name) + end + end + + return itemstack + end +}) diff --git a/mods/flowers/license.txt b/mods/flowers/license.txt new file mode 100644 index 0000000..419ebe5 --- /dev/null +++ b/mods/flowers/license.txt @@ -0,0 +1,63 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 Ironzorg, VanessaE +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2014-2016 RHRhino +Copyright (C) 2015-2016 Gambit +Copyright (C) 2016 yyt16384 +Copyright (C) 2017 paramat + +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/flowers/mapgen.lua b/mods/flowers/mapgen.lua new file mode 100644 index 0000000..ad759c2 --- /dev/null +++ b/mods/flowers/mapgen.lua @@ -0,0 +1,182 @@ +-- +-- Mgv6 +-- + +local function register_mgv6_flower(flower_name) + minetest.register_decoration({ + name = "flowers:"..flower_name, + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.006, + spread = {x = 100, y = 100, z = 100}, + seed = 436, + octaves = 3, + persist = 0.6 + }, + y_max = 30, + y_min = 1, + decoration = "flowers:"..flower_name, + }) +end + +local function register_mgv6_mushroom(mushroom_name) + minetest.register_decoration({ + name = "flowers:"..mushroom_name, + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.04, + spread = {x = 100, y = 100, z = 100}, + seed = 7133, + octaves = 3, + persist = 0.6 + }, + y_max = 30, + y_min = 1, + decoration = "flowers:"..mushroom_name, + spawn_by = "default:tree", + num_spawn_by = 1, + }) +end + +local function register_mgv6_waterlily() + minetest.register_decoration({ + name = "flowers:waterlily", + deco_type = "simple", + place_on = {"default:dirt"}, + sidelen = 16, + noise_params = { + offset = -0.12, + scale = 0.3, + spread = {x = 100, y = 100, z = 100}, + seed = 33, + octaves = 3, + persist = 0.7 + }, + y_max = 0, + y_min = 0, + decoration = "flowers:waterlily", + param2 = 0, + param2_max = 3, + place_offset_y = 1, + }) +end + +function flowers.register_mgv6_decorations() + register_mgv6_flower("rose") + register_mgv6_flower("tulip") + register_mgv6_flower("dandelion_yellow") + register_mgv6_flower("geranium") + register_mgv6_flower("viola") + register_mgv6_flower("dandelion_white") + + register_mgv6_mushroom("mushroom_brown") + register_mgv6_mushroom("mushroom_red") + + register_mgv6_waterlily() +end + + +-- +-- All other biome API mapgens +-- + +local function register_flower(seed, flower_name) + minetest.register_decoration({ + name = "flowers:"..flower_name, + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = -0.02, + scale = 0.04, + spread = {x = 200, y = 200, z = 200}, + seed = seed, + octaves = 3, + persist = 0.6 + }, + biomes = {"grassland", "deciduous_forest", "floatland_grassland"}, + y_max = 31000, + y_min = 1, + decoration = "flowers:"..flower_name, + }) +end + +local function register_mushroom(mushroom_name) + minetest.register_decoration({ + name = "flowers:"..mushroom_name, + deco_type = "simple", + place_on = {"default:dirt_with_grass", "default:dirt_with_coniferous_litter"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.006, + spread = {x = 250, y = 250, z = 250}, + seed = 2, + octaves = 3, + persist = 0.66 + }, + biomes = {"deciduous_forest", "coniferous_forest", + "floatland_coniferous_forest"}, + y_max = 31000, + y_min = 1, + decoration = "flowers:"..mushroom_name, + }) +end + +local function register_waterlily() + minetest.register_decoration({ + name = "default:waterlily", + deco_type = "simple", + place_on = {"default:dirt"}, + sidelen = 16, + noise_params = { + offset = -0.12, + scale = 0.3, + spread = {x = 200, y = 200, z = 200}, + seed = 33, + octaves = 3, + persist = 0.7 + }, + biomes = {"rainforest_swamp", "savanna_shore", "deciduous_forest_shore"}, + y_max = 0, + y_min = 0, + decoration = "flowers:waterlily", + param2 = 0, + param2_max = 3, + place_offset_y = 1, + }) +end + +function flowers.register_decorations() + register_flower(436, "rose") + register_flower(19822, "tulip") + register_flower(1220999, "dandelion_yellow") + register_flower(800081, "chrysanthemum_green") + register_flower(36662, "geranium") + register_flower(1133, "viola") + register_flower(73133, "dandelion_white") + register_flower(42, "tulip_black") + + register_mushroom("mushroom_brown") + register_mushroom("mushroom_red") + + register_waterlily() +end + + +-- +-- Detect mapgen to select functions +-- + +local mg_name = minetest.get_mapgen_setting("mg_name") +if mg_name == "v6" then + flowers.register_mgv6_decorations() +else + flowers.register_decorations() +end diff --git a/mods/flowers/textures/flowers_chrysanthemum_green.png b/mods/flowers/textures/flowers_chrysanthemum_green.png new file mode 100644 index 0000000..1198046 Binary files /dev/null and b/mods/flowers/textures/flowers_chrysanthemum_green.png differ diff --git a/mods/flowers/textures/flowers_dandelion_white.png b/mods/flowers/textures/flowers_dandelion_white.png new file mode 100644 index 0000000..1bc02fb Binary files /dev/null and b/mods/flowers/textures/flowers_dandelion_white.png differ diff --git a/mods/flowers/textures/flowers_dandelion_yellow.png b/mods/flowers/textures/flowers_dandelion_yellow.png new file mode 100644 index 0000000..544f60c Binary files /dev/null and b/mods/flowers/textures/flowers_dandelion_yellow.png differ diff --git a/mods/flowers/textures/flowers_geranium.png b/mods/flowers/textures/flowers_geranium.png new file mode 100644 index 0000000..88de1d7 Binary files /dev/null and b/mods/flowers/textures/flowers_geranium.png differ diff --git a/mods/flowers/textures/flowers_mushroom_brown.png b/mods/flowers/textures/flowers_mushroom_brown.png new file mode 100644 index 0000000..33ffcd4 Binary files /dev/null and b/mods/flowers/textures/flowers_mushroom_brown.png differ diff --git a/mods/flowers/textures/flowers_mushroom_red.png b/mods/flowers/textures/flowers_mushroom_red.png new file mode 100644 index 0000000..a68f5d5 Binary files /dev/null and b/mods/flowers/textures/flowers_mushroom_red.png differ diff --git a/mods/flowers/textures/flowers_rose.png b/mods/flowers/textures/flowers_rose.png new file mode 100644 index 0000000..e3b841d Binary files /dev/null and b/mods/flowers/textures/flowers_rose.png differ diff --git a/mods/flowers/textures/flowers_tulip.png b/mods/flowers/textures/flowers_tulip.png new file mode 100644 index 0000000..471fcd3 Binary files /dev/null and b/mods/flowers/textures/flowers_tulip.png differ diff --git a/mods/flowers/textures/flowers_tulip_black.png b/mods/flowers/textures/flowers_tulip_black.png new file mode 100644 index 0000000..1dd09f7 Binary files /dev/null and b/mods/flowers/textures/flowers_tulip_black.png differ diff --git a/mods/flowers/textures/flowers_viola.png b/mods/flowers/textures/flowers_viola.png new file mode 100644 index 0000000..ca2d750 Binary files /dev/null and b/mods/flowers/textures/flowers_viola.png differ diff --git a/mods/flowers/textures/flowers_waterlily.png b/mods/flowers/textures/flowers_waterlily.png new file mode 100644 index 0000000..305c445 Binary files /dev/null and b/mods/flowers/textures/flowers_waterlily.png differ diff --git a/mods/flowers/textures/flowers_waterlily_bottom.png b/mods/flowers/textures/flowers_waterlily_bottom.png new file mode 100644 index 0000000..3dbeaf4 Binary files /dev/null and b/mods/flowers/textures/flowers_waterlily_bottom.png differ diff --git a/mods/give_initial_stuff/README.txt b/mods/give_initial_stuff/README.txt new file mode 100644 index 0000000..cbd240f --- /dev/null +++ b/mods/give_initial_stuff/README.txt @@ -0,0 +1,8 @@ +Minetest Game mod: give_initial_stuff +===================================== +See license.txt for license information. + +Authors of source code +---------------------- +Perttu Ahola (celeron55) (MIT) +Various Minetest developers and contributors (MIT) diff --git a/mods/give_initial_stuff/depends.txt b/mods/give_initial_stuff/depends.txt new file mode 100644 index 0000000..3a7daa1 --- /dev/null +++ b/mods/give_initial_stuff/depends.txt @@ -0,0 +1,2 @@ +default + diff --git a/mods/give_initial_stuff/init.lua b/mods/give_initial_stuff/init.lua new file mode 100644 index 0000000..4f98f80 --- /dev/null +++ b/mods/give_initial_stuff/init.lua @@ -0,0 +1,44 @@ +local stuff_string = minetest.settings:get("initial_stuff") or + "default:pick_steel,default:axe_steel,default:shovel_steel," .. + "default:torch 99,default:cobble 99" + +give_initial_stuff = { + items = {} +} + +function give_initial_stuff.give(player) + --[[minetest.log("action", + "Giving initial stuff to player " .. player:get_player_name())]] + local inv = player:get_inventory() + for _, stack in ipairs(give_initial_stuff.items) do + inv:add_item("main", stack) + end +end + +function give_initial_stuff.add(stack) + give_initial_stuff.items[#give_initial_stuff.items + 1] = ItemStack(stack) +end + +function give_initial_stuff.clear() + give_initial_stuff.items = {} +end + +function give_initial_stuff.add_from_csv(str) + local items = str:split(",") + for _, itemname in ipairs(items) do + give_initial_stuff.add(itemname) + end +end + +function give_initial_stuff.set_list(list) + give_initial_stuff.items = list +end + +function give_initial_stuff.get_list() + return give_initial_stuff.items +end + +give_initial_stuff.add_from_csv(stuff_string) +if minetest.settings:get_bool("give_initial_stuff") then + minetest.register_on_newplayer(give_initial_stuff.give) +end diff --git a/mods/give_initial_stuff/license.txt b/mods/give_initial_stuff/license.txt new file mode 100644 index 0000000..8134c92 --- /dev/null +++ b/mods/give_initial_stuff/license.txt @@ -0,0 +1,25 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT diff --git a/mods/jas0/chatcommands.lua b/mods/jas0/chatcommands.lua new file mode 100644 index 0000000..802ad12 --- /dev/null +++ b/mods/jas0/chatcommands.lua @@ -0,0 +1,33 @@ +minetest.register_chatcommand("register", { + description = "Show registers", + privs = "server", + params = "none", + func = function(name, param) + print(dump(param)) + end +}) + +minetest.register_chatcommand("debug", { + description = "Debug command", + params = "", + privs = "server", + func = function(name, param) + local param = param:split(" ") + local name = minetest.get_player_by_name(name) + if param[1] == "wielded" then + if param[2] then + local bookq = param[2]:sub(1, 4) + local bookn = tonumber(param[2]:sub(5, -1)) + if bookq == "book" and bookn then + if bookn >= 1 and bookn <= 9 then + is.books[bookn] = name:get_wielded_item():to_table() + store:set_string("books", minetest.serialize(is.books)) + minetest.log("action", "Reboot to set initial stuff again.") + return true, "Reboot to set initial stuff again." + end + end + end + end + end, +}) + diff --git a/mods/jas0/classes.lua b/mods/jas0/classes.lua new file mode 100644 index 0000000..e8b45b7 --- /dev/null +++ b/mods/jas0/classes.lua @@ -0,0 +1,506 @@ +-- jas0/classes.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +local function particles(pos, texture) + return { + pos = pos, + velocity = {x = 0, y = 0.1, z = 0}, + acceleration = {x = 0, y = 0.01, z = 0}, + expirationtime = math.random(), + size = 0.34 + math.random() + math.random(), + collisiondetection = false, + collision_removal = false, + object_collision = false, + verticle = false, + texture = texture, + --playername = "singleplayer", + --animation = {Tile Animation definition}, + glow = 14, + } +end + +local old_item_drop = minetest.item_drop +minetest.item_drop = function(itemstack, dropper, pos) + if dropper:get_meta():get("class") == "node" then + return + else + return old_item_drop(itemstack, dropper, pos) + end +end +local function boom(pos) + local def = { + radius = 3, + } + return tnt.boom(pos, def) +end +minetest.register_entity("jas0:mage_fireball", { + description = "Fireball", + visual = "sprite", + textures = {"mobs_fireball.png"}, + glow = 14, + on_activate = function(self, staticdata, dtime_s) + self.owner = staticdata or "singleplayer" + end, + on_step = function(self, dtime) + local step = self.step or 0 + self.step = step + 1 + local pos = self.object:get_pos() + if step > 36 then + self.object:remove() + return boom(pos) + end + local objects = minetest.get_objects_inside_radius(pos, 0.85) + for i = 1, #objects do + if objects[i]:is_player() then + if objects[i]:get_player_name() ~= self.owner then + self.object:remove() + return boom(pos) + end + elseif objects[i]:get_luaentity().horny ~= nil then + -- It's a mob! + self.object:remove() + return boom(pos) + end + end + local node = minetest.get_node_or_nil(pos) + if not node then + return + end + local node_name = node.name + if not node_name then + return + end + local node_def = minetest.registered_nodes[node_name] + if not node_def then + return + end + local walkable = node_def.walkable + if not walkable then + return + end + self.object:remove() + return boom(pos) + end, +}) + +local generated = {} +for k, v in pairs(minetest.registered_nodes) do + if v.drawtype == "normal" then + generated[k] = "" + end +end +old_item_place_node = minetest.item_place_node +minetest.item_place_node = function(itemstack, placer, pointed_thing, param2, prevent_after_place) + if placer and placer:is_player() and placer:get_meta():get("class") == "node" then + local p = pointed_thing.above + if p then + placer:set_pos(p) + end + return + else + return old_item_place_node(itemstack, placer, pointed_thing, param2, prevent_after_place) + end +end + +minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) + if player:get_meta():get("class") == "node" then + return 0 + end +end) + +minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) + if node and node.name then + local meta = puncher:get_meta() + if meta:get("class") ~= "node" or + not generated[node.name] then + return + end + meta:set_string("node", node.name) + local inv = puncher:get_inventory() + inv:set_stack("main", 1, node.name) + puncher:set_properties({textures = {node.name}}) + end +end) + +minetest.register_tool("jas0:node", { + type = "none", + wield_image = "[combine:16x16", + range = 9, + stack_max = 1, + tool_capabilities = { + full_punch_interval = 2, + max_drop_level = 1, + groupcaps = { + crumbly = {}, + snappy = {}, + oddly_breakable_by_hand = {}, + }, + damage_groups = {fleshy = 0}, + }, +}) + +minetest.register_tool("jas0:mage", { + type = "none", + wield_image = "empty.png", + tool_capabilities = { + full_punch_interval = 2, + max_drop_level = 1, + groupcaps = { + crumbly = {}, + snappy = {}, + oddly_breakable_by_hand = {}, + }, + damage_groups = {fleshy = 0}, + }, +}) + +local function charge(player, amount) + if not player then + return + end + local pos = player:get_pos() + if not pos then + return + end + local meta = player:get_meta() + if not meta then + return minetest.after(0.1, charge, player, 0) + end + if meta:get_string("class") ~= "mage" then + return + end + local wielded_item = player:get_wielded_item() + if wielded_item:get_name() ~= "" then + if not minetest.registered_items[wielded_item:to_table().name].on_use then + local o = minetest.add_item(pos, wielded_item) + if o then + o:set_acceleration({ + x = 0, + y = -10, + z = 0, + }) + o:set_velocity({ + x = math.random(-3, 3), + y = math.random(0, 10), + z = math.random(-3, 3), + }) + end + player:set_wielded_item("") + end + return minetest.after(0.1, charge, player, 0) + end + pos.y = pos.y + 1.25 + local dir = player:get_look_dir() + if amount >= 9 then + pos = vector.add(pos, dir) + local arrow = minetest.add_entity(pos, "jas0:mage_fireball", player:get_player_name()) + arrow:set_acceleration(dir) + arrow:set_velocity(vector.multiply(dir, 12)) + player:set_hp(player:get_hp() * 0.8) + return minetest.after(0.1, charge, player, -9) + elseif amount < 0 then + return minetest.after(0.1, charge, player, amount + 0.25) + end + local ctrl = player:get_player_control() + if not ctrl.LMB then + return minetest.after(0.1, charge, player, 0) + else + if amount > 0 then + pos = vector.add(pos, dir) + minetest.add_particle(particles(pos, "default_item_smoke.png")) + minetest.add_particle(particles(pos, "tnt_smoke.png")) + minetest.add_particle(particles(pos, "default_mese_crystal.png")) + end + return minetest.after(0.1, charge, player, amount + 1) + end +end + +local formspec_prepend = {} +formspec_prepend.miner = "background[5,5;1,1;gui_formbg.png;true]" .. + "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" .. +"" + +formspec_prepend.mage = "background[5,5;1,1;gui_formbg.png;true]" .. + "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" .. +"" + +formspec_prepend.scout = "background[5,5;1,1;gui_formbg.png;true]" .. + "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" .. +"" + +formspec_prepend.node = "background[5,5;1,1;gui_formbg.png;true]" .. + "listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]" .. +"" + +local formspec = {} +formspec.miner = "size[8,8.5]" .. + jas0.exit_button() .. + "list[current_player;main;0,4.25;8,1]" .. + "list[current_player;main;0,5.5;8,3;8]" .. + "list[current_player;craft;2,0.5;3,3]" .. + "button_exit[0.25,1;1.5,1;spawn;Spawn]" .. + "button_exit[0.25,2;1.5,1;home;Home]" .. + "list[current_player;craftpreview;6,1.5;1,1]" .. + "image[5,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]" .. + "listring[current_player;main]" .. + "listring[current_player;craft]" .. + default.get_hotbar_bg(0, 4.25) .. +"" + +formspec.scout = "size[8,7.5]" .. + jas0.exit_button() .. + "list[current_player;main;0,4.25;8,1]" .. + "list[current_player;main;0,5.5;8,2;8]" .. + "list[current_player;craft;2,0.5;2,2]" .. + "button_exit[0.25,1;1.5,1;spawn;Spawn]" .. + "button_exit[0.25,2;1.5,1;home;Home]" .. + "list[current_player;craftpreview;6,1.5;1,1]" .. + "image[5,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]" .. + "listring[current_player;main]" .. + "listring[current_player;craft]" .. + default.get_hotbar_bg(0, 4.25) .. +"" + +formspec.mage = "size[8,5.5]" .. + jas0.exit_button() .. + "button_exit[0.25,1;1.5,1;spawn;Spawn]" .. + "button_exit[0.25,2;1.5,1;home;Home]" .. + "list[current_player;main;0,4.25;8,1;]" .. + "list[current_player;craft;3,1.5;1,1;]" .. + "image[4,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]" .. + "list[current_player;craftpreview;5,1.5;1,1;]" .. + "listring[current_player;main]" .. + "listring[current_player;craft]" .. + default.get_hotbar_bg(0, 4.25) .. +"" + +formspec.node = "size[8,5.5]" .. + jas0.exit_button() .. + "button_exit[0.25,1;1.5,1;spawn;Spawn]" .. + "button_exit[0.25,2;1.5,1;home;Home]" .. + "list[current_player;main;0,4.25;1,1;]" .. + --"list[current_player;craft;3,1.5;1,1;]" .. + --"image[4,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]" .. + --"list[current_player;craftpreview;5,1.5;1,1;]" .. + --"listring[current_player;main]" .. + --"listring[current_player;craft]" .. + default.get_hotbar_bg(0, 4.25, 1) .. +"" + +local function reset_skin(name) + local player = minetest.get_player_by_name(name) + if not player then + minetest.after(0.1, function() + reset_skin(name) + end) + end + local skin = player:get_meta():get_string("multiskin_skin") + multiskin.set_player_skin(player, skin) + multiskin.update_player_visuals(player) +end + +local function throw_contents(list, player, new_size) + if not list then + return + end + for i = new_size, #list, 1 do + local o = minetest.add_item(player:get_pos(), list[i]) + if o then + o:set_acceleration({ + x = 0, + y = -10, + z = 0, + }) + o:set_velocity({ + x = math.random(-3, 3), + y = math.random(0, 10), + z = math.random(-3, 3), + }) + end + end +end +local function class_update(player, class, reset) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + if class ~= "miner" and + class ~= "mage" and + class ~= "scout" and + class ~= "node" then + class = meta:get_string("class") + if class == "" then + class = "miner" + end + end + local level = jas0.level(player) + local inv = player:get_inventory() + local name = player:get_player_name() + if meta:get("class") == "node" then + inv:set_list("main", {}) + end + if class == "mage" then + meta:set_string("class", "mage") + player:set_formspec_prepend(formspec_prepend.mage) + if reset then + jas0.level(player, -level) + end + throw_contents(inv:get_list("main"), player, 8) + inv:set_size("main", 8) + inv:set_size("craft", 1) + inv:set_size("hand", 1) + inv:set_stack("hand", 1, "jas0:mage") + player:set_properties({ + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + eye_height = 1.47, + visual = "mesh", + visual_size = {x = 1, y = 1}, + }) + player:set_nametag_attributes({text = ""}) + charge(player, 0) + player:hud_set_hotbar_itemcount(8) + reset_skin(name) + player:hud_change(sneak_jump.meters[name].satiation, "number", + math.ceil(meta:get_float("satiation"))) + player:set_inventory_formspec(formspec.mage) + player:hud_set_flags({healthbar = true, wieldhand = true}) + player:hud_set_hotbar_itemcount(8) + elseif class == "miner" then + meta:set_string("class", "miner") + player:set_formspec_prepend(formspec_prepend.miner) + if reset then + jas0.level(player, -level) + end + inv:set_size("main", 8 * 4) + inv:set_size("craft", 3 * 3) + inv:set_list("hand", nil) + player:set_properties({ + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + eye_height = 1.47, + visual = "mesh", + visual_size = {x = 1, y = 1}, + }) + player:set_nametag_attributes({text = ""}) + player:hud_set_hotbar_itemcount(8) + reset_skin(name) + player:hud_change(sneak_jump.meters[name].satiation, "number", + math.ceil(meta:get_float("satiation"))) + player:set_inventory_formspec(formspec.miner) + player:hud_set_flags({healthbar = true, wieldhand = true}) + elseif class == "scout" then + meta:set_string("class", "scout") + player:set_formspec_prepend(formspec_prepend.scout) + if reset then + jas0.level(player, -level) + end + throw_contents(inv:get_list("main"), player, 24) + inv:set_size("main", 8 * 3) + inv:set_size("craft", 2 * 2) + inv:set_list("hand", nil) + player:set_properties({ + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + eye_height = 1.47, + visual = "mesh", + visual_size = {x = 1, y = 1}, + }) + player:set_nametag_attributes({text = ""}) + player:hud_set_hotbar_itemcount(8) + reset_skin(name) + player:hud_change(sneak_jump.meters[name].satiation, "number", + math.ceil(meta:get_float("satiation"))) + player:set_inventory_formspec(formspec.scout) + player:hud_set_flags({healthbar = true, wieldhand = true}) + elseif class == "node" then + meta:set_string("class", "node") + player:set_formspec_prepend(formspec_prepend.node) + if reset then + jas0.level(player, -level) + end + throw_contents(inv:get_list("main"), player, 0) + throw_contents(inv:get_list("craft"), player, 0) + inv:set_size("main", 1) + local n = meta:get("node") or "default:dirt" + inv:set_stack("main", 1, n) + inv:set_size("craft", 0) + inv:set_size("hand", 1) + inv:set_stack("hand", 1, "jas0:node") + player:set_properties({ + collisionbox = {-0.49, -0.49, -0.49, 0.49, 0.49, 0.49}, + eye_height = 0.07, + visual = "item", + visual_size = {x = 0.667, y = 0.667}, + textures = {n}, + }) + player:set_nametag_attributes({text = "\n"}) + player:hud_change(sneak_jump.meters[name].stamina, "number", 0) + player:hud_change(sneak_jump.meters[name].satiation, "number", 0) + + -- Prevent sunken position. + local p = player:get_pos() + p.y = p.y + 1 + player:set_pos(p) + + player:set_inventory_formspec(formspec.node) + minetest.after(0.1, function() + player:hud_set_hotbar_itemcount(1) + player:hud_set_flags({healthbar = false, wieldhand = false}) + end) + end + return class +end +jas0.change_class = function(player, class, reset) + class_update(player, class, reset) +end +minetest.register_on_joinplayer(function(player) + if not player then + return + end + local fb = class_update(player) + jas0.message(player:get_player_name(), "Your class is " .. fb) +end) + +-- /class command resets player's level! +minetest.register_chatcommand("class", { + description = "Change or display your class", + privs = "interact", + params = "[miner|mage|scout|node]", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + local class = meta:get_string("class") + -- Display class + if param ~= "mage" and + param ~= "miner" and + param ~= "scout" and + param ~= "node" then + return true, "Your current class is " .. class .. + ". Type /help class for more information." + end + -- Change class + if param == "mage" and class ~= "mage" then + class_update(player, "mage", true) + return true, "You are now a mage!" + elseif param == "miner" and class ~= "miner" then + class_update(player, "miner", true) + return true, "You are now a miner!" + elseif param == "scout" and class ~= "scout" then + class_update(player, "scout", true) + return true, "You are now a scout!" + elseif param == "node" and class ~= "node" then + class_update(player, "node", true) + return true, "You are now a node!" + else + return true, "You're already a " .. class .. "!" + end + end, +}) diff --git a/mods/jas0/depends.txt b/mods/jas0/depends.txt new file mode 100644 index 0000000..5202070 --- /dev/null +++ b/mods/jas0/depends.txt @@ -0,0 +1,3 @@ +bones +give_initial_stuff +sneak_jump diff --git a/mods/jas0/init.lua b/mods/jas0/init.lua new file mode 100644 index 0000000..a6a2e27 --- /dev/null +++ b/mods/jas0/init.lua @@ -0,0 +1,104 @@ +-- jas0 Glitchtest Support Mod +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +jas0 = {} + +local store = minetest.get_mod_storage() +local is = {} +is.books = minetest.deserialize(store:get_string("books")) or {} +for i = 1, #is.books do + give_initial_stuff.add(ItemStack(is.books[i])) +end + +minetest.register_on_joinplayer(function(player) + if not player then + return + end + minetest.after(0.1, function() + minetest.chat_send_player(player:get_player_name(), + "Hello. Welcome to Glitchtest server! " .. + "Type /help all for a list of commands.") + minetest.sound_play("sneak_jump_item", { + gain = 0.1, + pos = player:get_pos(), + }) + end) +end) + +minetest.register_on_chat_message(function(name, message) + local players = minetest.get_connected_players() + for i = 1, #players do + local f = minetest.sound_play("walkie_blip", { + object = players[i], + }) + minetest.sound_fade(f, -5, 0.25) + minetest.chat_send_player(players[i]:get_player_name(), + minetest.colorize("red", "<") .. + name .. minetest.colorize("red", "> ") .. + message) + end + return true +end) + +minetest.register_on_dieplayer(function(player) + if not player then + return + end + local p = minetest.pos_to_string(vector.round(player:get_pos())) + player:get_meta():set_string("death_location", p) +end) + +minetest.register_on_respawnplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + minetest.after(0.1, function() + minetest.chat_send_player(player:get_player_name(), + "Hello. Welcome to Glitchtest server! " .. + "Type /help all for a list of commands.") + minetest.sound_play("sneak_jump_item", { + gain = 0.1, + pos = player:get_pos(), + }) + end) + local inv = player:get_inventory() + if meta:get("class") == "node" then + inv:add_item("main", meta:get("node")) + return + end + local p = meta:get("death_location") + if p then + local ii = ItemStack("default:paper") + ii:get_meta():set_string("description", "Died at " .. p) + inv:add_item("main", ItemStack(ii)) + end + inv:add_item("main", "walkie:talkie") + for i = 1, #is.books do + inv:add_item("main", ItemStack(is.books[i])) + end +end) + +-- OVERRIDES +minetest.override_item("bones:bones", { + on_use = minetest.item_eat(1) +}) +minetest.override_item("farming:seed_wheat", { + on_use = minetest.item_eat(1) +}) +minetest.override_item("farming:seed_cotton", { + on_use = minetest.item_eat(1) +}) + +local mod_name = minetest.get_current_modname() +local mod_path = minetest.get_modpath(mod_name) +dofile(mod_path .. "/paper.lua") +dofile(mod_path .. "/ui.lua") +dofile(mod_path .. "/players.lua") +dofile(mod_path .. "/classes.lua") +dofile(mod_path .. "/recipes.lua") +dofile(mod_path .. "/chatcommands.lua") diff --git a/mods/jas0/paper.lua b/mods/jas0/paper.lua new file mode 100644 index 0000000..966206f --- /dev/null +++ b/mods/jas0/paper.lua @@ -0,0 +1,93 @@ +-- jas0/paper.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +local paper_on_place = function(itemstack, player, pointed_thing) + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + local pdef = minetest.registered_nodes[node.name] + if pdef and pdef.on_rightclick then + return pdef.on_rightclick(pointed_thing.under, + node, player, itemstack, pointed_thing) + end + end + local count = itemstack:get_count() + local desc = itemstack:get_meta():get_string("description") + local text = "" + if desc ~= "Paper" then + text = desc + end + minetest.show_formspec(player:get_player_name(), "default:paper", + "field[text;;" .. text .. "]") +end + +minetest.override_item("default:paper", { + on_use = minetest.item_eat(1), + on_place = function(itemstack, placer, pointed_thing) + paper_on_place(itemstack, placer, pointed_thing) + end, + on_secondary_use = function(itemstack, user, pointed_thing) + paper_on_place(itemstack, user, pointed_thing) + end, +}) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if not player then + return + end + if formname ~= "default:paper" then + return + end + if fields.text then + local count = player:get_wielded_item():get_count() + local is = ItemStack({name = "default:paper"}) + is:get_meta():set_string("description", fields.text) + player:set_wielded_item(is) + if count > 1 then + local iii = player:get_inventory():add_item("main", "default:paper " .. tostring(count - 1)) + if iii then + minetest.add_item(player:get_pos(), iii) + end + end + end +end) + +local paper_display = {} +local function paper_displayer(player) + if not player then + return + end + local name = player:get_player_name() + local wielded = player:get_wielded_item() + local text = wielded:get_meta():get_string("description") + if wielded:get_name() ~= "default:paper" or + text == "" or + text == "Paper" then + if paper_display[name] then + player:hud_remove(paper_display[name]) + paper_display[name] = nil + end + return minetest.after(0.1, paper_displayer, player) + end + local hd = { + hud_elem_type = "text", + position = {x = 0.0334, y = 0.667}, + alignment = {x = 1, y = 1}, + direction = 1, + text = text, + number = 0xFFFFFF, + } + if not paper_display[name] then + paper_display[name] = player:hud_add(hd) + return minetest.after(0.1, paper_displayer, player) + end + player:hud_change(paper_display[name], + "text", text) + minetest.after(0.1, paper_displayer, player) +end +minetest.register_on_joinplayer(function(player) + if not player then + return + end + minetest.after(0.1, paper_displayer, player) +end) diff --git a/mods/jas0/players.lua b/mods/jas0/players.lua new file mode 100644 index 0000000..c1fae59 --- /dev/null +++ b/mods/jas0/players.lua @@ -0,0 +1,164 @@ +-- jas0/players.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +local players = {} +local function level(player, repeater) + if not player then + return + end + local name = player:get_player_name() + if not players[name] then + return + end + local l = players[name] + local h = player:get_properties().hp_max + if l >= 0 and l < 30 and + h ~= 20 then + jas0.message(name, "Setting HP Max 20!") + player:set_properties({hp_max = 20,}) + elseif l >= 30 and l < 40 and + h ~= 30 then + jas0.message(name, "Setting HP Max 30!") + player:set_properties({hp_max = 30,}) + elseif l >= 40 and l < 50 and + h ~= 40 then + jas0.message(name, "Setting HP Max 40!") + player:set_properties({hp_max = 40,}) + elseif l >= 50 and l < 60 and + h ~= 50 then + jas0.message(name, "Setting HP Max 50!") + player:set_properties({hp_max = 50,}) + elseif l >= 60 and l < 70 and + h ~= 60 then + jas0.message(name, "Setting HP Max 60!") + player:set_properties({hp_max = 60,}) + elseif l >= 70 and l < 80 and + h ~= 70 then + jas0.message(name, "Setting HP Max 70!") + player:set_properties({hp_max = 70,}) + elseif l >= 80 and l < 90 and + h ~= 80 then + jas0.message(name, "Setting HP Max 80!") + player:set_properties({hp_max = 80,}) + elseif l >= 90 and l < 99 and + h ~= 90 then + jas0.message(name, "Setting HP Max 90!") + player:set_properties({hp_max = 90,}) + elseif l >= 99 and h ~= 99 then + jas0.message(name, "Setting HP Max 99! The MAX!!") + player:set_properties({hp_max = 99,}) + end + if players[name] >= 99 then + if players[name] > 99 then + players[name] = 99 + return + else + return + end + end + if sneak_jump.cdr(player) then + players[name] = players[name] + 0.1 + else + players[name] = players[name] + 0.01 + end + if repeater then + minetest.after(2, level, player) + end +end + +jas0.level = function(player, change) + if not player then + return + end + local name = player:get_player_name() + if not change then + return players[name] + end + if not players[name] or + (change > 0 and players[name] >= 99) then + return + end + players[name] = players[name] + change + level(player, false) +end +minetest.register_on_joinplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + local name = player:get_player_name() + if player:get_hp() ~= 0 then + local hp = meta:get_int("hp") + if hp == 0 then + hp = 20 + end + if hp then + jas0.message(name, + "Attempting to restore HP!") + minetest.after(0.12, function() + player:set_hp(hp) + end) + end + end + local l = meta:get_float("level") + players[name] = l + level(player) +end) + +minetest.register_on_respawnplayer(function(player) + if not player or not player:get_properties() then + return + end + players[player:get_player_name()] = 0 + player:set_properties({hp_max = 20,}) +end) + +local function save(player) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + local hp = player:get_hp() + local name = player:get_player_name() + meta:set_float("level", players[name]) + meta:set_int("hp", hp) +end +minetest.register_on_leaveplayer(function(player) + -- This doesn't run if the server shuts down. + save(player) +end) +minetest.register_chatcommand("save", { + description = "Save player class and level.", + params = "none", + privs = "interact", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return false, "Player not found." + end + save(player) + return true, "Player class and level saved." + end, +}) +minetest.register_on_shutdown(function() + local m = minetest.get_connected_players() + for i = 1, #m do + save(m[1]) + end +end) + +minetest.register_chatcommand("level", { + description = "Show level", + params = "none", + privs = "interact", + func = function(name, param) + local player = minetest.get_player_by_name(name) + return true, "Level: " .. tostring(jas0.level(player)) .. ", " .. + "HP " .. tostring(player:get_hp()) .. " / " .. + tostring(player:get_properties().hp_max) + end, +}) diff --git a/mods/jas0/recipes.lua b/mods/jas0/recipes.lua new file mode 100644 index 0000000..50894fe --- /dev/null +++ b/mods/jas0/recipes.lua @@ -0,0 +1,63 @@ +-- jas0/recipes.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +minetest.register_craft({ + output = "default:stick", + type = "shapeless", + recipe = {"group:tool",} +}) + +minetest.register_craft({ + output = "dye:white", + type = "shapeless", + recipe = {"bones:bones",} +}) + +minetest.register_craft({ + output = "default:book", + type = "shapeless", + recipe = {"dye:white", "default:book_written",} +}) + +minetest.register_craft({ + output = "mobs:leather 2", + type = "shapeless", + recipe = {"backpacks:backpack_leather",} +}) + +minetest.register_craft({ + output = "default:paper", + type = "shapeless", + recipe = {"default:book_written",} +}) + +minetest.register_craft({ + output = "default:paper", + type = "shapeless", + recipe = {"default:book",} +}) + +minetest.register_craft({ + output = "default:book", + type = "shapeless", + recipe = {"craftguide:book",} +}) + +minetest.register_craft({ + output = "craftguide:book", + type = "shapeless", + recipe = {"default:book", "walkie:talkie",} +}) + +minetest.register_craft({ + output = "craftguide:book", + type = "shapeless", + recipe = {"default:book_written", "walkie:talkie",} +}) + +minetest.register_craft({ + output = "default:steel_ingot", + type = "shapeless", + recipe = {"walkie:talkie",} +}) diff --git a/mods/jas0/sounds/default_chest_close.ogg b/mods/jas0/sounds/default_chest_close.ogg new file mode 100644 index 0000000..7993990 Binary files /dev/null and b/mods/jas0/sounds/default_chest_close.ogg differ diff --git a/mods/jas0/sounds/default_dig_crumbly.ogg b/mods/jas0/sounds/default_dig_crumbly.ogg new file mode 100644 index 0000000..1f10cf0 Binary files /dev/null and b/mods/jas0/sounds/default_dig_crumbly.ogg differ diff --git a/mods/jas0/sounds/default_dig_snappy.ogg b/mods/jas0/sounds/default_dig_snappy.ogg new file mode 100644 index 0000000..a25400d Binary files /dev/null and b/mods/jas0/sounds/default_dig_snappy.ogg differ diff --git a/mods/jas0/sounds/default_dirt_footstep.1.ogg b/mods/jas0/sounds/default_dirt_footstep.1.ogg new file mode 100644 index 0000000..f6220e9 Binary files /dev/null and b/mods/jas0/sounds/default_dirt_footstep.1.ogg differ diff --git a/mods/jas0/sounds/default_dirt_footstep.2.ogg b/mods/jas0/sounds/default_dirt_footstep.2.ogg new file mode 100644 index 0000000..62a3296 Binary files /dev/null and b/mods/jas0/sounds/default_dirt_footstep.2.ogg differ diff --git a/mods/jas0/sounds/default_grass_footstep.1.ogg b/mods/jas0/sounds/default_grass_footstep.1.ogg new file mode 100644 index 0000000..2c1c38d Binary files /dev/null and b/mods/jas0/sounds/default_grass_footstep.1.ogg differ diff --git a/mods/jas0/sounds/default_grass_footstep.2.ogg b/mods/jas0/sounds/default_grass_footstep.2.ogg new file mode 100644 index 0000000..6bb2497 Binary files /dev/null and b/mods/jas0/sounds/default_grass_footstep.2.ogg differ diff --git a/mods/jas0/sounds/default_grass_footstep.3.ogg b/mods/jas0/sounds/default_grass_footstep.3.ogg new file mode 100644 index 0000000..30468ce Binary files /dev/null and b/mods/jas0/sounds/default_grass_footstep.3.ogg differ diff --git a/mods/jas0/sounds/doors_door_close.ogg b/mods/jas0/sounds/doors_door_close.ogg new file mode 100644 index 0000000..9855d19 Binary files /dev/null and b/mods/jas0/sounds/doors_door_close.ogg differ diff --git a/mods/jas0/sounds/doors_door_open.ogg b/mods/jas0/sounds/doors_door_open.ogg new file mode 100644 index 0000000..28b1bba Binary files /dev/null and b/mods/jas0/sounds/doors_door_open.ogg differ diff --git a/mods/jas0/sounds/doors_fencegate_close.ogg b/mods/jas0/sounds/doors_fencegate_close.ogg new file mode 100644 index 0000000..ad9a5d1 Binary files /dev/null and b/mods/jas0/sounds/doors_fencegate_close.ogg differ diff --git a/mods/jas0/sounds/doors_fencegate_open.ogg b/mods/jas0/sounds/doors_fencegate_open.ogg new file mode 100644 index 0000000..58262df Binary files /dev/null and b/mods/jas0/sounds/doors_fencegate_open.ogg differ diff --git a/mods/jas0/sounds/doors_glass_door_close.ogg b/mods/jas0/sounds/doors_glass_door_close.ogg new file mode 100644 index 0000000..9adbcab Binary files /dev/null and b/mods/jas0/sounds/doors_glass_door_close.ogg differ diff --git a/mods/jas0/sounds/doors_glass_door_open.ogg b/mods/jas0/sounds/doors_glass_door_open.ogg new file mode 100644 index 0000000..66e6812 Binary files /dev/null and b/mods/jas0/sounds/doors_glass_door_open.ogg differ diff --git a/mods/jas0/sounds/doors_steel_door_close.ogg b/mods/jas0/sounds/doors_steel_door_close.ogg new file mode 100644 index 0000000..991c981 Binary files /dev/null and b/mods/jas0/sounds/doors_steel_door_close.ogg differ diff --git a/mods/jas0/sounds/doors_steel_door_open.ogg b/mods/jas0/sounds/doors_steel_door_open.ogg new file mode 100644 index 0000000..eb1c073 Binary files /dev/null and b/mods/jas0/sounds/doors_steel_door_open.ogg differ diff --git a/mods/jas0/sounds/xdecor_bouncy.ogg b/mods/jas0/sounds/xdecor_bouncy.ogg new file mode 100644 index 0000000..779e825 Binary files /dev/null and b/mods/jas0/sounds/xdecor_bouncy.ogg differ diff --git a/mods/jas0/textures/crosshair.png b/mods/jas0/textures/crosshair.png new file mode 100644 index 0000000..cb822ce Binary files /dev/null and b/mods/jas0/textures/crosshair.png differ diff --git a/mods/jas0/textures/empty.png b/mods/jas0/textures/empty.png new file mode 100644 index 0000000..0b800ab Binary files /dev/null and b/mods/jas0/textures/empty.png differ diff --git a/mods/jas0/ui.lua b/mods/jas0/ui.lua new file mode 100644 index 0000000..fd0e692 --- /dev/null +++ b/mods/jas0/ui.lua @@ -0,0 +1,116 @@ +-- jas0/ui.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +jas0.exit_button = function(x, y) + if not x then + x = 0 + end + if not y then + y = 0 + end + return "button_exit[" .. 7.44 + x .. "," .. + -0.034 + y .. ";0.7,0.667;;x]" +end + +jas0.help_button = function(x, y) + if not x then + x = 0 + end + if not y then + y = 0 + end + return "button_exit[" .. 6.94 + x .. "," .. + -0.034 + y .. ";0.7,0.667;help;?]" +end + +local log1 = {["walkie"] = { + ["nowield"] = "You need to wield a Walkie Talkie in your hand to warp home!", + ["spawn"] = "You need to wield a Walkie Talkie in your hand to respawn!", + ["home"] = "You don't have a home! To set your home, " .. + "activate an Intercomm using your " .. + "Walkie Talkie, or [Set Home] using a Bed." .. + "", +}} + +local function message(player, message, dialog, formname, title, no_chat_msg) + if not player then + return + end + + local name + if type(player) == "string" then + name = player + player = minetest.get_player_by_name(name) + else + name = player:get_player_name() + end + + if not message then + message = "This space intentionally left blank." + end + + if not no_chat_msg then + minetest.chat_send_player(name, message) + end + + message = minetest.formspec_escape(message) + local formspec = "size[8,4]" .. + jas0.exit_button() .. + "textarea[0.35,0.5;8,4;;;" .. + message .. "]" .. + "" + if title then + formspec = formspec .. "label[0,0;" .. title .. "]" + end + + if formname then + formspec = formspec .. + "button_exit[1,3;2,1;cancel;Cancel]" .. + "button_exit[6,3;1,1;ok;OK]" .. + "" + else + formname = "jas0:message_dialog" + end + + if dialog then + return minetest.after(0, minetest.show_formspec, + name, formname, formspec) + else + return formspec + end +end + +jas0.message = message + + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "" then + return false + end + local wielded = player:get_wielded_item():get_name() + local name = player:get_player_name() + if fields.spawn then + if wielded == "walkie:talkie" then + if beds.spawn[name] then + player:set_pos(beds.spawn[name]) + else + spawn.on_spawn(player) + end + else + message(name, log1["walkie"]["spawn"], true) + return false + end + elseif fields.home then + if walkie.players[name].waypoints.saved then + if wielded ~= "walkie:talkie" then + message(name, log1["walkie"]["nowield"], true) + return false + end + player:set_pos(walkie.players[name].waypoints.saved) + else + message(name, log1["walkie"]["home"], true) + return false + end + end +end) diff --git a/mods/mailbox/LICENSE b/mods/mailbox/LICENSE new file mode 100644 index 0000000..16c4ab4 --- /dev/null +++ b/mods/mailbox/LICENSE @@ -0,0 +1,682 @@ ++----------------------------------------------------------------------+ +| Glitchtest is copyright (c) 2018 James Stevenson | +| | +| Code: GPL version 3 | +| Media: CC BY-SA 4 ++----------------------------------------------------------------------+ + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/mods/mailbox/LICENSE.xdecor b/mods/mailbox/LICENSE.xdecor new file mode 100644 index 0000000..8b744c6 --- /dev/null +++ b/mods/mailbox/LICENSE.xdecor @@ -0,0 +1,39 @@ +┌──────────────────────────────────────────────────────────────────────┐ +│ Copyright (c) 2015-2017 kilbith │ +│ │ +│ Code: BSD │ +│ Textures: WTFPL (credits: Gambit, kilbith, Cisoun) │ +│ Sounds: │ +│ - xdecor_boiling_water.ogg - by Audionautics - CC BY-SA │ +│ freesound.org/people/Audionautics/sounds/133901/ │ +│ - xdecor_enchanting.ogg - by Timbre - CC BY-SA-NC │ +│ freesound.org/people/Timbre/sounds/221683/ │ +│ - xdecor_bouncy.ogg - by Blender Foundation - CC BY 3.0 │ +│ opengameart.org/content/funny-comic-cartoon-bounce-sound │ +└──────────────────────────────────────────────────────────────────────┘ + + +Copyright (c) 1998, Regents of the University of California +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of the University of California, Berkeley nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mods/mailbox/README b/mods/mailbox/README new file mode 100644 index 0000000..a1f9297 --- /dev/null +++ b/mods/mailbox/README @@ -0,0 +1,3 @@ +This is a Mailbox mod, featuring textures from jp's X-Decor mod (see LICENSE.xdecor). + +The code is from scratch. diff --git a/mods/mailbox/depends.txt b/mods/mailbox/depends.txt new file mode 100644 index 0000000..bfd7366 --- /dev/null +++ b/mods/mailbox/depends.txt @@ -0,0 +1 @@ +jas0 diff --git a/mods/mailbox/init.lua b/mods/mailbox/init.lua new file mode 100644 index 0000000..1e3914f --- /dev/null +++ b/mods/mailbox/init.lua @@ -0,0 +1,102 @@ +-- Mailbox mod for Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + + +minetest.register_craft({ + output = "mailbox:mailbox", + recipe = { + {"default:clay_brick", "default:steel_ingot", "default:clay_brick"}, + {"default:steel_ingot", "default:paper", "default:steel_ingot"}, + {"default:clay_brick", "default:steel_ingot", "default:clay_brick"}, + }, +}) + +minetest.register_node("mailbox:mailbox", { + description = "Mailbox", + tiles = { + "mailbox_top.png", + "mailbox_botton.png", + "mailbox_side.png", + "mailbox_side.png", + "mailbox_logo.png", + "mailbox_logo.png", + }, + paramtype2 = "facedir", + groups = {cracky = 3}, + after_place_node = function(pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + if not meta then + return + end + local name = placer:get_player_name() + meta:set_string("owner", name) + meta:set_string("infotext", name .. "'s Mailbox") + local inv = meta:get_inventory() + if not inv then + return + end + inv:set_size("mailbox", 8 * 4) + inv:set_size("send", 1) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + if not player then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local name = player:get_player_name() + if name == meta:get_string("owner") then + return + end + + local inv = meta:get_inventory() + local overflow = inv:add_item("mailbox", stack) + inv:set_list("send", {}) + if overflow:get_name() == "" then + elseif overflow then + pos.y = pos.y + 1 + minetest.add_item(pos, overflow) + minetest.chat_send_player(name, "Mailbox is full!") + end + end, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not clicker then + return + end + local meta = minetest.get_meta(pos) + if not meta then + return + end + local inv = meta:get_inventory() + pos = minetest.pos_to_string(pos):sub(2, -2) + local name = clicker:get_player_name() + local owner = meta:get_string("owner") + if owner ~= name then + minetest.show_formspec(name, "mailbox:send", + "size[8,5.667;]" .. + jas0.exit_button() .. + "label[0,0;Send " .. owner .. " some mail!]" .. + "list[nodemeta:" .. pos .. ";send;3.5,0.667;1,1]" .. + "list[current_player;main;0,1.9;8,1]" .. + "list[current_player;main;0,3;8,3;8]" .. + "listring[nodemeta:" .. pos .. ";send]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 1.9) .. + "") + return + end + minetest.show_formspec(name, "mailbox:mailbox", + "size[8,8.334]" .. + "list[nodemeta:" .. pos .. ";mailbox;0,0;8,4;]" .. + "list[current_player;main;0,4.5;8,1;]" .. + "list[current_player;main;0,5.6;8,3;8]" .. + "listring[nodemeta:" .. pos .. ";mailbox]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 4.5) .. + "") + end, + 0 +}) diff --git a/mods/mailbox/textures/mailbox_blank16.png b/mods/mailbox/textures/mailbox_blank16.png new file mode 100644 index 0000000..017d4f9 Binary files /dev/null and b/mods/mailbox/textures/mailbox_blank16.png differ diff --git a/mods/mailbox/textures/mailbox_botton.png b/mods/mailbox/textures/mailbox_botton.png new file mode 100644 index 0000000..b613863 Binary files /dev/null and b/mods/mailbox/textures/mailbox_botton.png differ diff --git a/mods/mailbox/textures/mailbox_logo.png b/mods/mailbox/textures/mailbox_logo.png new file mode 100644 index 0000000..8289884 Binary files /dev/null and b/mods/mailbox/textures/mailbox_logo.png differ diff --git a/mods/mailbox/textures/mailbox_side.png b/mods/mailbox/textures/mailbox_side.png new file mode 100644 index 0000000..44b2a2f Binary files /dev/null and b/mods/mailbox/textures/mailbox_side.png differ diff --git a/mods/mailbox/textures/mailbox_top.png b/mods/mailbox/textures/mailbox_top.png new file mode 100644 index 0000000..3584c53 Binary files /dev/null and b/mods/mailbox/textures/mailbox_top.png differ diff --git a/mods/mechanisms/LICENSE.txt b/mods/mechanisms/LICENSE.txt new file mode 100644 index 0000000..205cac2 --- /dev/null +++ b/mods/mechanisms/LICENSE.txt @@ -0,0 +1,682 @@ ++----------------------------------------------------------------------+ +| Copyright (c) 2015-2016 kilbith | +| | +| Code: GPL version 3 | +| Textures: WTFPL (credits: Gambit, kilbith, Cisoun) | ++----------------------------------------------------------------------+ + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/mods/mechanisms/README.txt b/mods/mechanisms/README.txt new file mode 100644 index 0000000..fada21d --- /dev/null +++ b/mods/mechanisms/README.txt @@ -0,0 +1,22 @@ +=== +From mechanisms.lua: + +--[[ Thanks to sofar for helping with that code. +Pressure plates work better with this setting in minetest.conf (requires 0.4.14): + nodetimer_interval = 0.1 +]] +== + + + +## X-Decor ## + +##### A decoration mod meant to be simple and well-featured. ##### +##### It adds a bunch of cute cubes, various mechanisms and stuff for [cutting](https://forum.minetest.net/viewtopic.php?f=11&t=14085), [enchanting](https://forum.minetest.net/viewtopic.php?f=11&t=14087), cooking, etc. ##### +##### This mod is a lightweight alternative to Home Decor and More Blocks all together. ##### + +### Credits ### + +##### Special thanks to Gambit for the textures from the PixelBOX pack for Minetest. ##### + +![Preview](http://i.imgur.com/AVoyCQy.png) diff --git a/mods/mechanisms/depends.txt b/mods/mechanisms/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/mechanisms/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/mechanisms/init.lua b/mods/mechanisms/init.lua new file mode 100644 index 0000000..2681bc6 --- /dev/null +++ b/mods/mechanisms/init.lua @@ -0,0 +1,156 @@ +--[[ Thanks to sofar for helping with that code. +Recommended setting in minetest.conf (requires 0.4.14 or newer) : + nodetimer_interval = 0.1 +]] + +local plate = {} +screwdriver = screwdriver or {} + +local function door_toggle(pos_actuator, pos_door, player) + local actuator = minetest.get_node(pos_actuator) + local door = doors.get(pos_door) + + if actuator.name:sub(-4) == "_off" then + minetest.set_node(pos_actuator, + {name=actuator.name:gsub("_off", "_on"), param2=actuator.param2}) + end + door:open(player) + + minetest.after(2, function() + if minetest.get_node(pos_actuator).name:sub(-3) == "_on" then + minetest.set_node(pos_actuator, + {name=actuator.name, param2=actuator.param2}) + end + door:close() + end) +end + +function plate.construct(pos) + local timer = minetest.get_node_timer(pos) + timer:start(0.1) +end + +function plate.timer(pos) + local objs = minetest.get_objects_inside_radius(pos, 0.8) + if objs == {} or not doors.get then return true end + local minp = {x=pos.x-2, y=pos.y, z=pos.z-2} + local maxp = {x=pos.x+2, y=pos.y, z=pos.z+2} + local doors = minetest.find_nodes_in_area(minp, maxp, "group:door") + + for _, player in pairs(objs) do + if player:is_player() then + for i = 1, #doors do + door_toggle(pos, doors[i], player) + end + break + end + end + return true +end + +function plate.register(material, desc, def) + minetest.register_node("mechanisms:pressure_"..material.."_off", { + description = desc.." Pressure Plate", + tiles = {"mechanisms_pressure_"..material..".png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-0.4375, -0.5, -0.4375, 0.4375, -0.4375, 0.4375}} + }, + groups = def.groups, + sounds = def.sounds, + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + on_rotate = screwdriver.rotate_simple, + on_construct = plate.construct, + on_timer = plate.timer + }) + minetest.register_node("mechanisms:pressure_"..material.."_on", { + tiles = {"mechanisms_pressure_"..material..".png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-0.4375, -0.5, -0.4375, 0.4375, -0.475, 0.4375}} + }, + groups = def.groups, + sounds = def.sounds, + drop = "mechanisms:pressure_"..material.."_off", + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + on_rotate = screwdriver.rotate_simple + }) +end +--[[ +plate.register("wood", "Wooden", { + sounds = default.node_sound_wood_defaults(), + groups = {choppy=3, oddly_breakable_by_hand=2, flammable=2} +}) +]] +plate.register("stone", "Stone", { + sounds = default.node_sound_stone_defaults(), + groups = {cracky=3, oddly_breakable_by_hand=2} +}) + +minetest.register_node("mechanisms:lever_off", { + description = "Lever", + tiles = {"mechanisms_lever_off.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-0.375, -0.4375, 0.4375, 0.375, 0.4375, 0.5}} + }, + groups = {cracky=3, oddly_breakable_by_hand=2}, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + on_rotate = screwdriver.rotate_simple, + on_rightclick = function(pos, node, clicker) + if not doors.get then return end + local minp = {x=pos.x-2, y=pos.y-1, z=pos.z-2} + local maxp = {x=pos.x+2, y=pos.y+1, z=pos.z+2} + local doors = minetest.find_nodes_in_area(minp, maxp, "group:door") + + for i = 1, #doors do + door_toggle(pos, doors[i], clicker) + end + end +}) + +minetest.register_node("mechanisms:lever_on", { + tiles = {"mechanisms_lever_on.png"}, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {{-0.375, -0.4375, 0.4375, 0.375, 0.4375, 0.5}} + }, + groups = {cracky=3, oddly_breakable_by_hand=2, not_in_creative_inventory=1}, + sounds = default.node_sound_stone_defaults(), + sunlight_propagates = true, + paramtype = "light", + paramtype2 = "facedir", + on_rotate = screwdriver.rotate_simple, + drop = "mechanisms:lever_off" +}) +--[[ +minetest.register_craft({ + type = "shapeless", + output = "mechanisms:pressure_wood_off", + recipe = {"default:wood", "default:wood"} +}) +--]] +minetest.register_craft({ + type = "shapeless", + output = "mechanisms:pressure_stone_off", + recipe = {"default:stone", "default:stone"} +}) + +minetest.register_craft({ + output = "mechanisms:lever_off", + recipe = { + {"default:stick"}, + {"default:stone"} + } +}) diff --git a/mods/mechanisms/mod.conf b/mods/mechanisms/mod.conf new file mode 100644 index 0000000..509463c --- /dev/null +++ b/mods/mechanisms/mod.conf @@ -0,0 +1 @@ +name = mechanisms diff --git a/mods/mechanisms/textures/mechanisms_lever_off.png b/mods/mechanisms/textures/mechanisms_lever_off.png new file mode 100644 index 0000000..143ad88 Binary files /dev/null and b/mods/mechanisms/textures/mechanisms_lever_off.png differ diff --git a/mods/mechanisms/textures/mechanisms_lever_on.png b/mods/mechanisms/textures/mechanisms_lever_on.png new file mode 100644 index 0000000..933d138 Binary files /dev/null and b/mods/mechanisms/textures/mechanisms_lever_on.png differ diff --git a/mods/mechanisms/textures/mechanisms_pressure_stone.png b/mods/mechanisms/textures/mechanisms_pressure_stone.png new file mode 100644 index 0000000..899e8f2 Binary files /dev/null and b/mods/mechanisms/textures/mechanisms_pressure_stone.png differ diff --git a/mods/mobs/AUTHORS b/mods/mobs/AUTHORS new file mode 100644 index 0000000..e5221ac --- /dev/null +++ b/mods/mobs/AUTHORS @@ -0,0 +1,6 @@ +NPC mob by TenPlus1 +Female NPC skin by nuttmeg20 +"NPC Baby" skin by AmirDerAssassine + +mobs_swing.ogg by qubodup (http://freesound.org/people/qubodup/sounds/60012/) +mobs_spell.og by littlerobotsoundfactory (http://freesound.org/people/LittleRobotSoundFactory/sounds/270396/) diff --git a/mods/mobs/LICENSE.sounds b/mods/mobs/LICENSE.sounds new file mode 100644 index 0000000..3b160fe --- /dev/null +++ b/mods/mobs/LICENSE.sounds @@ -0,0 +1,7 @@ +Creative Commons sounds from Freesound.org + +mobs_swing.ogg by qubodup + - http://freesound.org/people/qubodup/sounds/60012/ + +mobs_spell.ogg by littlerobotsoundfactory + - http://freesound.org/people/LittleRobotSoundFactory/sounds/270396/ diff --git a/mods/mobs/LICENSE.zombies b/mods/mobs/LICENSE.zombies new file mode 100644 index 0000000..fb0b15a --- /dev/null +++ b/mods/mobs/LICENSE.zombies @@ -0,0 +1,6 @@ +Zombie model derived from the default player model. + +Textures Created by me, Nathan +CC by SA 3.0 + +Code copy/pasted with minor changes from Tenplus1's mob API, licensed as MIT. diff --git a/mods/mobs/api.lua b/mods/mobs/api.lua new file mode 100644 index 0000000..76e872f --- /dev/null +++ b/mods/mobs/api.lua @@ -0,0 +1,3918 @@ +-- mobs are part of Glitchtest +-- Glitchtest is Copyright 2018 James Stevenson +-- Released under the GNU GPL 3 + +-- mobs_redo by TenPlus1 & Co. + + +-- Intllib and CMI support check +local MP = minetest.get_modpath(minetest.get_current_modname()) +local S, NS = dofile(MP .. "/intllib.lua") +local use_cmi = minetest.global_exists("cmi") + +mobs = { + mod = "redo", + version = "20180915", + intllib = S, + invis = minetest.global_exists("invisibility") and invisibility or {}, +} + +-- creative check +local creative_cache = minetest.settings:get_bool("creative_mode") +function mobs.is_creative(name) + return creative_cache or minetest.check_player_privs(name, {creative = true}) +end + + +-- localize math functions +local pi = math.pi +local square = math.sqrt +local sin = math.sin +local cos = math.cos +local abs = math.abs +local min = math.min +local max = math.max +local atann = math.atan +local random = math.random +print(random(20)) +local floor = math.floor +local atan = function(x) + if not x or x ~= x then + --error("atan bassed NaN") + return 0 + else + return atann(x) + end +end + + +-- Load settings +local damage_enabled = minetest.settings:get_bool("enable_damage") +local mobs_spawn = minetest.settings:get_bool("mobs_spawn") ~= false +local peaceful_only = minetest.settings:get_bool("only_peaceful_mobs") +local disable_blood = minetest.settings:get_bool("mobs_disable_blood") +local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false +local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local creative = minetest.settings:get_bool("creative_mode") +local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false +local remove_far = minetest.settings:get_bool("remove_far_mobs") ~= false +local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 +local show_health = minetest.settings:get_bool("mob_show_health") ~= false +local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 99) +local mob_chance_multiplier = tonumber(minetest.settings:get("mob_chance_multiplier") or 1) + +-- Peaceful mode message so players will know there are no monsters +if peaceful_only then + minetest.register_on_joinplayer(function(player) + minetest.chat_send_player(player:get_player_name(), + S("** Peaceful Mode Active - No Monsters Will Spawn")) + end) +end + +-- calculate aoc range for mob count +local aoc_range = tonumber(minetest.settings:get("active_block_range")) * 16 + +-- pathfinding settings +local enable_pathfinding = false +local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching +local stuck_path_timeout = 10 -- how long will mob follow path before giving up + +-- default nodes +local node_fire = "fire:basic_flame" +local node_permanent_flame = "fire:permanent_flame" +local node_ice = "default:ice" +local node_snowblock = "default:snowblock" +local node_snow = "default:snow" +mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "default:dirt" + + +-- play sound +local mob_sound = function(self, sound, gain, pitch, delay) + if sound then + local gain = gain or random(60, 93) / 100 + random() / 11 + local pitch = pitch or 0.96 + random(1, 7) / 100 + random() / 11 + local sh = minetest.sound_play(sound, { + gain = self.sounds.gain or gain, + pitch = pitch, + object = self.object, + max_hear_distance = self.sounds.distance or 64, + }) + delay = delay or 0.5 + minetest.after(delay, minetest.sound_fade, sh, -1, 0.0) + end +end + +-- attack player/mob +local do_attack = function(self, player) + + if self.state == "attack" then + return + end + + self.attack = player + self.state = "attack" + + if random(0, 100) < 90 then + mob_sound(self, self.sounds.war_cry) + end +end + + +-- calculate distance +local get_distance = function(a, b) + + local x, y, z = a.x - b.x, a.y - b.y, a.z - b.z + + return square(x * x + y * y + z * z) +end + +-- collision function based on similar from jordan4ibanez' open_ai mod +local collision = function(self) + local pos = self.object:get_pos() + local vel = self.object:get_velocity() + local x, z = 0, 0 + local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 + for _, object in ipairs(minetest.get_objects_inside_radius(pos, width)) do + if not object:is_player() or + not object:get_luaentity() then + break + end + if object:is_player() or + (object:get_luaentity()._cmi_is_mob == true and + object ~= self.object) then + local pos2 = object:get_pos() + local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} + x = x + vec.x + z = z + vec.z + end + end + return {x, z} +end + +-- move mob in facing direction +local set_velocity = function(self, v) + local c_x, c_y = 0, 0 + -- can mob be pushed, if so calculate direction + if self.pushable then + c_x, c_y = unpack(collision(self)) + end + -- halt mob if it has been ordered to stay + --[[ + if self.order == "stand" then + self.object:set_velocity({x = 0, y = 0, z = 0}) + return + end + --]] + local yaw = (self.object:get_yaw() or 0) + self.rotate + self.object:set_velocity({ + x = (sin(yaw) * -v) + c_x, + y = self.object:get_velocity().y, + z = (cos(yaw) * v) + c_y, + }) +end + + +-- calculate mob velocity +local get_velocity = function(self) + + local v = self.object:get_velocity() + + return (v.x * v.x + v.z * v.z) ^ 0.5 +end + + +-- set and return valid yaw +local set_yaw = function(self, yaw, delay) + + if not yaw or yaw ~= yaw then + yaw = 0 + end + + delay = delay or 0 + + if delay == 0 then + self.object:set_yaw(yaw) + return yaw + end + + self.target_yaw = yaw + self.delay = delay + + return self.target_yaw +end + +-- global function to set mob yaw +function mobs:yaw(self, yaw, delay) + set_yaw(self, yaw, delay) +end + + +-- set defined animation +local set_animation = function(self, anim) + + if not self.animation + or not anim then return end + + self.animation.current = self.animation.current or "" + + -- only set different animation for attacks when setting to same set + if anim ~= "punch" and anim ~= "shoot" + and string.find(self.animation.current, anim) then + return + end + + -- check for more than one animation + local num = 0 + + for n = 1, 4 do + + if self.animation[anim .. n .. "_start"] + and self.animation[anim .. n .. "_end"] then + num = n + end + end + + -- choose random animation from set + if num > 0 then + num = random(0, num) + anim = anim .. (num ~= 0 and num or "") + end + + if anim == self.animation.current + or not self.animation[anim .. "_start"] + or not self.animation[anim .. "_end"] then + return + end + + self.animation.current = anim + + self.object:set_animation({ + x = self.animation[anim .. "_start"], + y = self.animation[anim .. "_end"]}, + self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, + 0, self.animation[anim .. "_loop"] ~= false) +end + +-- above function exported for mount.lua +function mobs:set_animation(self, anim) + set_animation(self, anim) +end + + +-- check line of sight (by BrunoMine, tweaked by Astrobe) +local line_of_sight = function(self, pos1, pos2, stepsize) + + if not pos1 or not pos2 then return end + + stepsize = stepsize or 1 + + local stepv = vector.multiply(vector.direction(pos1, pos2), stepsize) + + local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) + + -- normal walking and flying mobs can see you through air + if s == true then return true end + + -- New pos1 to be analyzed + local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} + + local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + -- Checks the return + if r == true then return true end + + -- Nodename found + local nn = minetest.get_node(pos).name + + -- It continues to advance in the line of sight in search of a real + -- obstruction which counts as 'normal' nodebox. + while minetest.registered_nodes[nn] + and (minetest.registered_nodes[nn].walkable == false) do +-- or minetest.registered_nodes[nn].drawtype == "nodebox") do + + npos1 = vector.add(npos1, stepv) + + if get_distance(npos1, pos2) < stepsize then return true end + + -- scan again + r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + + if r == true then return true end + + -- New Nodename found + nn = minetest.get_node(pos).name + end + + return false +end + +-- global function +function mobs:line_of_sight(self, pos1, pos2, stepsize) + + return line_of_sight(self, pos1, pos2, stepsize) +end + + +-- are we flying in what we are suppose to? (taikedz) +local flight_check = function(self, pos_w) + + local def = minetest.registered_nodes[self.standing_in] + + if not def then return false end -- nil check + + if type(self.fly_in) == "string" + and self.standing_in == self.fly_in then + + return true + + elseif type(self.fly_in) == "table" then + + for _,fly_in in pairs(self.fly_in) do + + if self.standing_in == fly_in then + + return true + end + end + end + + -- stops mobs getting stuck inside stairs and plantlike nodes + if def.drawtype ~= "airlike" + and def.drawtype ~= "liquid" + and def.drawtype ~= "flowingliquid" then + return true + end + + return false +end + + +-- custom particle effects +local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow) + + radius = radius or 2 + min_size = min_size or 0.5 + max_size = max_size or 1 + gravity = gravity or -10 + glow = glow or 0 + + minetest.add_particlespawner({ + amount = amount, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x = -radius, y = -radius, z = -radius}, + maxvel = {x = radius, y = radius, z = radius}, + minacc = {x = 0, y = gravity, z = 0}, + maxacc = {x = 0, y = gravity, z = 0}, + minexptime = 0.1, + maxexptime = 1, + minsize = min_size, + maxsize = max_size, + texture = texture, + glow = glow, + }) +end + + +-- update nametag colour +local update_tag = function(self) + + local col = "#00FF00" + local qua = self.hp_max / 4 + + if self.health <= floor(qua * 3) then + col = "#FFFF00" + end + + if self.health <= floor(qua * 2) then + col = "#FF6600" + end + + if self.health <= floor(qua) then + col = "#FF0000" + end + + self.object:set_properties({ + nametag = self.nametag, + nametag_color = col + }) + +end + + +-- drop items +local item_drop = function(self) + + -- check for nil or no drops + if not self.drops or #self.drops == 0 then + return + end + + -- no drops if disabled by setting + if not mobs_drop_items then return end + + -- no drops for child mobs + if self.child then return end + + -- was mob killed by player? + local death_by_player = self.cause_of_death and self.cause_of_death.puncher + and self.cause_of_death.puncher:is_player() or nil + + local obj, item, num + local pos = self.object:get_pos() + + for n = 1, #self.drops do + + if random(1, self.drops[n].chance) == 1 then + + num = random(self.drops[n].min or 0, self.drops[n].max or 1) + item = self.drops[n].name + + -- cook items on a hot death + if self.cause_of_death.hot then + + local output = minetest.get_craft_result({ + method = "cooking", width = 1, items = {item}}) + + if output and output.item and not output.item:is_empty() then + item = output.item:get_name() + end + end + + -- only drop rare items (drops.min=0) if killed by player + if death_by_player then + obj = minetest.add_item(pos, ItemStack(item .. " " .. num)) + + elseif self.drops[n].min ~= 0 then + obj = minetest.add_item(pos, ItemStack(item .. " " .. num)) + end + + if obj and obj:get_luaentity() then + + obj:set_velocity({ + x = random(-10, 10) / 9, + y = 6, + z = random(-10, 10) / 9, + }) + + elseif obj then + obj:remove() -- item does not exist + end + end + end + + self.drops = {} +end + + +-- check if mob is dead or only hurt +local check_for_death = function(self, cmi_cause) + + -- has health actually changed? + if self.health == self.old_health and self.health > 0 then + return + end + + self.old_health = self.health + + -- still got some health? play hurt sound + if self.health > 0 then + + mob_sound(self, self.sounds.damage) + + -- make sure health isn't higher than max + if self.health > self.hp_max then + self.health = self.hp_max + end + --[[ + -- backup nametag so we can show health stats + if not self.nametag2 then + self.nametag2 = self.nametag or "" + end + + if show_health + and (cmi_cause and cmi_cause.type == "punch") then + + self.htimer = 2 + self.nametag = "♥ " .. self.health .. " / " .. self.hp_max + --]] + update_tag(self)--[[ + end + --]] + return false + end + + self.cause_of_death = cmi_cause + + -- drop items + item_drop(self) + + mob_sound(self, self.sounds.death) + + local pos = self.object:get_pos() + + -- execute custom death function + if self.on_die then + + self.on_die(self, pos) + + if use_cmi then + cmi.notify_die(self.object, cmi_cause) + end + + self.object:remove() + + return true + end + + -- default death function and die animation (if defined) + if self.animation + and self.animation.die_start + and self.animation.die_end then + + local frames = self.animation.die_end - self.animation.die_start + local speed = self.animation.die_speed or 15 + local length = max(frames / speed, 0) + + self.attack = nil + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.passive = true + self.state = "die" + set_velocity(self, 0) + set_animation(self, "die") + + minetest.after(length, function(self) + + if use_cmi and self.object:get_luaentity() then + cmi.notify_die(self.object, cmi_cause) + end + + self.object:remove() + end, self) + else + + if use_cmi then + cmi.notify_die(self.object, cmi_cause) + end + + self.object:remove() + end + + effect(pos, 20, "tnt_smoke.png") + + return true +end + + +-- is mob facing a cliff +local is_at_cliff = function(self) + + if self.fear_height == 0 then -- 0 for no falling protection! + return false + end + + local yaw = self.object:get_yaw() + local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) + local pos = self.object:get_pos() + local ypos = pos.y + self.collisionbox[2] -- just above floor + + if minetest.line_of_sight( + {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, + {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z} + , 1) then + + return true + end + + return false +end + + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + + fallback = fallback or mobs.fallback_node + + local node = minetest.get_node_or_nil(pos) + + if node and minetest.registered_nodes[node.name] then + return node + end + + return minetest.registered_nodes[fallback] +end + + +-- environmental damage (water, lava, fire, light etc.) +local do_env_damage = function(self) + + -- feed/tame text timer (so mob 'full' messages dont spam chat) + if self.htimer > 0 then + self.htimer = self.htimer - 1 + end + --[[ + -- reset nametag after showing health stats + if self.htimer < 1 and self.nametag2 then + + self.nametag = self.nametag2 + self.nametag2 = nil + --]] + update_tag(self) --[[ + end --]] + local pos = self.object:get_pos() + + self.time_of_day = minetest.get_timeofday() + + -- remove mob if standing inside ignore node + if self.standing_in == "ignore" then + self.object:remove() + return + end + + -- is mob light sensative, or scared of the dark :P + if self.light_damage ~= 0 then + + local light = minetest.get_node_light(pos) or 0 + + if light >= self.light_damage_min + and light <= self.light_damage_max then + + self.health = self.health - self.light_damage + + effect(pos, 5, "tnt_smoke.png") + + if check_for_death(self, {type = "light"}) then return end + end + end + + local nodef = minetest.registered_nodes[self.standing_in] + + pos.y = pos.y + 1 -- for particle effect position + + -- water + if self.water_damage + and nodef.groups.water then + + if self.water_damage ~= 0 then + + self.health = self.health - self.water_damage + + effect(pos, 5, "bubble.png", nil, nil, 1, nil) + + if check_for_death(self, {type = "environment", + pos = pos, node = self.standing_in}) then return end + end + + -- lava or fire or ignition source + elseif self.lava_damage + and nodef.groups.igniter then +-- and (nodef.groups.lava +-- or self.standing_in == node_fire +-- or self.standing_in == node_permanent_flame) then + + if self.lava_damage ~= 0 then + + self.health = self.health - self.lava_damage + + effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) + + if check_for_death(self, {type = "environment", + pos = pos, node = self.standing_in, hot = true}) then return end + end + + -- damage_per_second node check + elseif nodef.damage_per_second ~= 0 then + + self.health = self.health - nodef.damage_per_second + + effect(pos, 5, "tnt_smoke.png") + + if check_for_death(self, {type = "environment", + pos = pos, node = self.standing_in}) then return end + end +--[[ + --- suffocation inside solid node + if self.suffocation ~= 0 + and nodef.walkable == true + and nodef.groups.disable_suffocation ~= 1 + and nodef.drawtype == "normal" then + + self.health = self.health - self.suffocation + + if check_for_death(self, {type = "environment", + pos = pos, node = self.standing_in}) then return end + end +]] + check_for_death(self, {type = "unknown"}) +end + + +-- jump if facing a solid node (not fences or gates) +local do_jump = function(self) + + if not self.jump + or self.jump_height == 0 + or self.fly + or self.child + or self.order == "stand" then + return false + end + + self.facing_fence = false + + -- something stopping us while moving? + if self.state ~= "stand" + and get_velocity(self) > 0.5 + and self.object:get_velocity().y ~= 0 then + return false + end + + local pos = self.object:get_pos() + local yaw = self.object:get_yaw() + + -- what is mob standing on? + pos.y = pos.y + self.collisionbox[2] - 0.2 + + local nod = node_ok(pos) + +--print ("standing on:", nod.name, pos.y) + + if minetest.registered_nodes[nod.name].walkable == false then + return false + end + + -- where is front + local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) + + -- what is in front of mob? + local nod = node_ok({ + x = pos.x + dir_x, + y = pos.y + 0.5, + z = pos.z + dir_z + }) + + -- thin blocks that do not need to be jumped + if nod.name == node_snow then + return false + end + +--print ("in front:", nod.name, pos.y + 0.5) + + if self.walk_chance == 0 + or minetest.registered_items[nod.name].walkable then + + if not nod.name:find("fence") + and not nod.name:find("gate") then + + local v = self.object:get_velocity() + + v.y = self.jump_height + + set_animation(self, "jump") -- only when defined + + self.object:set_velocity(v) + + -- when in air move forward + minetest.after(0.3, function(self, v) + + if self.object:get_luaentity() then + + self.object:set_acceleration({ + x = v.x * 2,--1.5, + y = 0, + z = v.z * 2,--1.5 + }) + end + end, self, v) + + if get_velocity(self) > 0 then + mob_sound(self, self.sounds.jump) + end + else + self.facing_fence = true + end + + return true + end + + return false +end + + +-- blast damage to entities nearby (modified from TNT mod) +local entity_physics = function(pos, radius) + + radius = radius * 2 + + local objs = minetest.get_objects_inside_radius(pos, radius) + local obj_pos, dist + + for n = 1, #objs do + + obj_pos = objs[n]:get_pos() + + dist = get_distance(pos, obj_pos) + if dist < 1 then dist = 1 end + + local damage = floor((4 / dist) * radius) + local ent = objs[n]:get_luaentity() + + -- punches work on entities AND players + objs[n]:punch(objs[n], 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, pos) + end +end + + +-- should mob follow what I'm holding ? +local follow_holding = function(self, clicker) + + if mobs.invis[clicker:get_player_name()] then + return false + end + + local item = clicker:get_wielded_item() + local t = type(self.follow) + + -- single item + if t == "string" + and item:get_name() == self.follow then + return true + + -- multiple items + elseif t == "table" then + + for no = 1, #self.follow do + + if self.follow[no] == item:get_name() then + return true + end + end + end + + return false +end + + +-- find two animals of same type and breed if nearby and horny +local breed = function(self) + + -- child takes 240 seconds before growing into adult + if self.child == true then + + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer > 240 then + + self.child = false + self.hornytimer = 0 + + self.object:set_properties({ + textures = self.base_texture, + mesh = self.base_mesh, + visual_size = self.base_size, + collisionbox = self.base_colbox, + selectionbox = self.base_selbox, + }) + + -- custom function when child grows up + if self.on_grown then + self.on_grown(self) + else + -- jump when fully grown so as not to fall into ground + self.object:set_velocity({ + x = 0, + y = self.jump_height, + z = 0 + }) + end + end + + return + end + + -- horny animal can mate for 40 seconds, + -- afterwards horny animal cannot mate again for 200 seconds + if self.horny == true + and self.hornytimer < 240 then + + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer >= 240 then + self.hornytimer = 0 + self.horny = false + end + end + + -- find another same animal who is also horny and mate if nearby + if self.horny == true + and self.hornytimer <= 40 then + + local pos = self.object:get_pos() + + effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) + + local objs = minetest.get_objects_inside_radius(pos, 3) + local num = 0 + local ent = nil + + for n = 1, #objs do + + ent = objs[n]:get_luaentity() + + -- check for same animal with different colour + local canmate = false + + if ent then + + if ent.name == self.name then + canmate = true + else + local entname = string.split(ent.name,":") + local selfname = string.split(self.name,":") + + if entname[1] == selfname[1] then + entname = string.split(entname[2],"_") + selfname = string.split(selfname[2],"_") + + if entname[1] == selfname[1] then + canmate = true + end + end + end + end + + if ent + and canmate == true + and ent.horny == true + and ent.hornytimer <= 40 then + num = num + 1 + end + + -- found your mate? then have a baby + if num > 1 then + + self.hornytimer = 41 + ent.hornytimer = 41 + + -- spawn baby + minetest.after(5, function(self, ent) + + if not self.object:get_luaentity() then + return + end + + -- custom breed function + if self.on_breed then + + -- when false skip going any further + if self.on_breed(self, ent) == false then + return + end + else + effect(pos, 15, "tnt_smoke.png", 1, 2, 2, 15, 5) + end + + local mob = minetest.add_entity(pos, self.name) + local ent2 = mob:get_luaentity() + local textures = self.base_texture + + -- using specific child texture (if found) + if self.child_texture then + textures = self.child_texture[1] + end + + -- and resize to half height + mob:set_properties({ + textures = textures, + visual_size = { + x = self.base_size.x * .5, + y = self.base_size.y * .5, + }, + collisionbox = { + self.base_colbox[1] * .5, + self.base_colbox[2] * .5, + self.base_colbox[3] * .5, + self.base_colbox[4] * .5, + self.base_colbox[5] * .5, + self.base_colbox[6] * .5, + }, + selectionbox = { + self.base_selbox[1] * .5, + self.base_selbox[2] * .5, + self.base_selbox[3] * .5, + self.base_selbox[4] * .5, + self.base_selbox[5] * .5, + self.base_selbox[6] * .5, + }, + }) + -- tamed and owned by parents' owner + ent2.child = true + ent2.tamed = true + ent2.owner = self.owner + end, self, ent) + + num = 0 + + break + end + end + end +end + + +-- find and replace what mob is looking for (grass, wheat etc.) +local replace = function(self, pos) + + if not mobs_griefing + or not self.replace_rate + or not self.replace_what + or self.child == true + or self.object:get_velocity().y ~= 0 + or random(1, self.replace_rate) > 1 then + return + end + + local what, with, y_offset + + if type(self.replace_what[1]) == "table" then + + local num = random(#self.replace_what) + + what = self.replace_what[num][1] or "" + with = self.replace_what[num][2] or "" + y_offset = self.replace_what[num][3] or 0 + else + what = self.replace_what + with = self.replace_with or "" + y_offset = self.replace_offset or 0 + end + + pos.y = pos.y + y_offset + + if #minetest.find_nodes_in_area(pos, pos, what) > 0 then + +-- print ("replace node = ".. minetest.get_node(pos).name, pos.y) + + local oldnode = {name = what} + local newnode = {name = with} + local on_replace_return + + if self.on_replace then + on_replace_return = self.on_replace(self, pos, oldnode, newnode) + end + + if on_replace_return ~= false then + + minetest.set_node(pos, {name = with}) + + -- when cow/sheep eats grass, replace wool and milk + if self.gotten == true then + self.gotten = false + self.object:set_properties(self) + end + end + end +end + + +-- check if daytime and also if mob is docile during daylight hours +local day_docile = function(self) + + if self.docile_by_day == false then + + return false + + elseif self.docile_by_day == true + and self.time_of_day > 0.2 + and self.time_of_day < 0.8 then + + return true + end +end + + +local los_switcher = false +local height_switcher = false + +-- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 +local smart_mobs = function(self, s, p, dist, dtime) + + local s1 = self.path.lastpos + + local target_pos = self.attack:get_pos() + + -- is it becoming stuck? + if abs(s1.x - s.x) + abs(s1.z - s.z) < .5 then + self.path.stuck_timer = self.path.stuck_timer + dtime + else + self.path.stuck_timer = 0 + end + + self.path.lastpos = {x = s.x, y = s.y, z = s.z} + + local use_pathfind = false + local has_lineofsight = minetest.line_of_sight( + {x = s.x, y = (s.y) + .5, z = s.z}, + {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) + + -- im stuck, search for path + if not has_lineofsight then + + if los_switcher == true then + use_pathfind = true + los_switcher = false + end -- cannot see target! + else + if los_switcher == false then + + los_switcher = true + use_pathfind = false + + minetest.after(1, function(self) + + if self.object:get_luaentity() then + + if has_lineofsight then + self.path.following = false + end + end + end, self) + end -- can see target! + end + + if (self.path.stuck_timer > stuck_timeout and not self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + + if self.object:get_luaentity() then + + if has_lineofsight then + self.path.following = false + end + end + end, self) + end + + if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest.after(1, function(self) + + if self.object:get_luaentity() then + + if has_lineofsight then + self.path.following = false + end + end + end, self) + end + + if abs(vector.subtract(s,target_pos).y) > self.stepheight then + + if height_switcher then + use_pathfind = true + height_switcher = false + end + else + if not height_switcher then + use_pathfind = false + height_switcher = true + end + end + + if use_pathfind then + -- lets try find a path, first take care of positions + -- since pathfinder is very sensitive + local sheight = self.collisionbox[5] - self.collisionbox[2] + + -- round position to center of node to avoid stuck in walls + -- also adjust height for player models! + s.x = floor(s.x + 0.5) +-- s.y = floor(s.y + 0.5) - sheight + s.z = floor(s.z + 0.5) + + local ssight, sground = minetest.line_of_sight(s, { + x = s.x, y = s.y - 4, z = s.z}, 1) + + -- determine node above ground + if not ssight then + s.y = sground.y + 1 + end + + local p1 = self.attack:get_pos() + + p1.x = floor(p1.x + 0.5) + p1.y = floor(p1.y + 0.5) + p1.z = floor(p1.z + 0.5) + + local dropheight = 6 + if self.fear_height ~= 0 then dropheight = self.fear_height end + + self.path.way = minetest.find_path(s, p1, 16, self.stepheight, dropheight, "Dijkstra") + +--[[ + -- show path using particles + if self.path.way and #self.path.way > 0 then + print ("-- path length:" .. tonumber(#self.path.way)) + for _,pos in pairs(self.path.way) do + minetest.add_particle({ + pos = pos, + velocity = {x=0, y=0, z=0}, + acceleration = {x=0, y=0, z=0}, + expirationtime = 1, + size = 4, + collisiondetection = false, + vertical = false, + texture = "heart.png", + }) + end + end +]] + + self.state = "" + do_attack(self, self.attack) + + -- no path found, try something else + if not self.path.way then + + self.path.following = false + + -- lets make way by digging/building if not accessible + if self.pathfinding == 2 and mobs_griefing then + + -- is player higher than mob? + if s.y < p1.y then + + -- build upwards + if not minetest.is_protected(s, "") then + + local ndef1 = minetest.registered_nodes[self.standing_in] + + if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then + + minetest.set_node(s, {name = mobs.fallback_node}) + end + end + + local sheight = math.ceil(self.collisionbox[5]) + 1 + + -- assume mob is 2 blocks high so it digs above its head + s.y = s.y + sheight + + -- remove one block above to make room to jump + if not minetest.is_protected(s, "") then + + local node1 = node_ok(s, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.set_node(s, {name = "air"}) + minetest.add_item(s, ItemStack(node1)) + + end + end + + s.y = s.y - sheight + self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) + + else -- dig 2 blocks to make door toward player direction + + local yaw1 = self.object:get_yaw() + pi / 2 + local p1 = { + x = s.x + cos(yaw1), + y = s.y, + z = s.z + sin(yaw1) + } + + if not minetest.is_protected(p1, "") then + + local node1 = node_ok(p1, "air").name + local ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + p1.y = p1.y + 1 + node1 = node_ok(p1, "air").name + ndef1 = minetest.registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest.add_item(p1, ItemStack(node1)) + minetest.set_node(p1, {name = "air"}) + end + + end + end + end + + -- will try again in 2 second + self.path.stuck_timer = stuck_timeout - 2 + + -- frustration! cant find the damn path :( + mob_sound(self, self.sounds.random) + else + -- yay i found path + mob_sound(self, self.sounds.war_cry) + set_velocity(self, self.walk_velocity) + + -- follow path now that it has it + self.path.following = true + end + end +end + + +-- specific attacks +local specific_attack = function(list, what) + + -- no list so attack default (player, animals etc.) + if list == nil then + return true + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- general attack function for all mobs ========== +local general_attack = function(self) + + -- return if already attacking, passive or docile during day + if self.passive + or self.state == "attack" + or day_docile(self) then + return + end + + local s = self.object:get_pos() + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + -- remove entities we aren't interested in + for n = 1, #objs do + + local ent = objs[n]:get_luaentity() + + -- are we a player? + if objs[n]:is_player() then + + -- if player invisible or mob not setup to attack then remove from list + if self.attack_players == false + or (self.owner and self.type ~= "monster") + or mobs.invis[objs[n]:get_player_name()] + or not specific_attack(self.specific_attack, "player") then + objs[n] = nil +--print("- pla", n) + end + + -- or are we a mob? + elseif ent and ent._cmi_is_mob then + + -- remove mobs not to attack + if self.name == ent.name + or (not self.attack_animals and ent.type == "animal") + or (not self.attack_monsters and ent.type == "monster") + or (not self.attack_npcs and ent.type == "npc") + or not specific_attack(self.specific_attack, ent.name) then + objs[n] = nil +--print("- mob", n, self.name, ent.name) + end + + -- remove all other entities + else +--print(" -obj", n) + objs[n] = nil + end + end + + local p, sp, dist, min_player + local min_dist = self.view_range + 1 + + -- go through remaining entities and select closest + for _,player in pairs(objs) do + + p = player:get_pos() + sp = s + + dist = get_distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + -- choose closest player to attack that isnt self + if dist ~= 0 + and dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + + -- attack closest player or mob + if min_player then + do_attack(self, min_player) + end +end + + +-- specific runaway +local specific_runaway = function(list, what) + + -- no list so do not run + if list == nil then + return false + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- find someone to runaway from +local runaway_from = function(self) + + if not self.runaway_from then + return + end + + local s = self.object:get_pos() + local p, sp, dist, pname + local player, obj, min_player, name + local min_dist = self.view_range + 1 + local objs = minetest.get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + pname = objs[n]:get_player_name() + + if mobs.invis[pname] + or self.owner == pname then + + name = "" + else + player = objs[n] + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + name = obj.name or "" + end + end + + -- find specific mob to runaway from + if name ~= "" and name ~= self.name + and specific_runaway(self.runaway_from, name) then + + p = player:get_pos() + sp = s + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + dist = get_distance(p, s) + + -- choose closest player/mob to runaway from + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + if min_player then + + local lp = player:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + pi + end + + yaw = set_yaw(self, yaw, 4) + self.state = "runaway" + self.runaway_timer = 3 + self.following = nil + end +end + + +-- follow player if owner or holding item, if fish outta water then flop +local follow_flop = function(self) + + -- find player to follow + if (self.follow ~= "" + or self.order == "follow") + and not self.following + and self.state ~= "attack" + and self.state ~= "runaway" then + + local s = self.object:get_pos() + local players = minetest.get_connected_players() + + for n = 1, #players do + + if get_distance(players[n]:get_pos(), s) < self.view_range + and not mobs.invis[ players[n]:get_player_name() ] then + + self.following = players[n] + + break + end + end + end + + if self.type == "npc" + and self.order == "follow" + and self.state ~= "attack" + and self.owner ~= "" then + + -- npc stop following player if not owner + if self.following + and self.owner + and self.owner ~= self.following:get_player_name() then + self.following = nil + end + else + -- stop following player if not holding specific item + if self.following + and self.following:is_player() + and follow_holding(self, self.following) == false then + self.following = nil + end + + end + + -- follow that thing + if self.following then + + local s = self.object:get_pos() + local p + + if self.following:is_player() then + + p = self.following:get_pos() + + elseif self.following.object then + + p = self.following.object:get_pos() + end + + if p then + + local dist = get_distance(p, s) + + -- dont follow if out of range + if dist > self.view_range then + self.following = nil + else + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + pi end + + yaw = set_yaw(self, yaw, 6) + + -- anyone but standing npc's can move along + if dist > self.reach + and self.order ~= "stand" then + + set_velocity(self, self.walk_velocity) + + -- mob plays random sound at times + if random(1, 100) == 1 then + mob_sound(self, self.sounds.random) + end + if self.walk_chance ~= 0 then + set_animation(self, "walk") + end + else + set_velocity(self, 0) + set_animation(self, "stand") + end + + return + end + end + end + + -- swimmers flop when out of their element, and swim again when back in + if self.fly then + local s = self.object:get_pos() + if not flight_check(self, s) then + + self.state = "flop" + self.object:set_velocity({x = 0, y = -5, z = 0}) + + set_animation(self, "stand") + + return + elseif self.state == "flop" then + self.state = "stand" + end + end +end + + +-- dogshoot attack switch and counter function +local dogswitch = function(self, dtime) + + -- switch mode not activated + if not self.dogshoot_switch + or not dtime then + return 0 + end + + self.dogshoot_count = self.dogshoot_count + dtime + + if (self.dogshoot_switch == 1 + and self.dogshoot_count > self.dogshoot_count_max) + or (self.dogshoot_switch == 2 + and self.dogshoot_count > self.dogshoot_count2_max) then + + self.dogshoot_count = 0 + + if self.dogshoot_switch == 1 then + self.dogshoot_switch = 2 + else + self.dogshoot_switch = 1 + end + end + + return self.dogshoot_switch +end + + +-- execute current state (stand, walk, run, attacks) +local do_states = function(self, dtime) + + local yaw = self.object:get_yaw() or 0 + + if self.state == "stand" then + + if random(1, 4) == 1 then + + local lp = nil + local s = self.object:get_pos() + local objs = minetest.get_objects_inside_radius(s, 2) + + for n = 1, #objs do + + if objs[n]:is_player() then + lp = objs[n]:get_pos() + break + end + end + + -- look at any players nearby, otherwise turn randomly + if lp then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if lp.x > s.x then yaw = yaw + pi end + else + yaw = yaw + random(-0.5, 0.5) + self.order = "follow" + end + + yaw = set_yaw(self, yaw, 8) + end + + set_velocity(self, 0) + set_animation(self, "stand") + + -- mobs ordered to stand stay standing + if self.order ~= "stand" + and self.walk_chance ~= 0 + and self.facing_fence ~= true + and random(1, 100) <= self.walk_chance + and is_at_cliff(self) == false then + + set_velocity(self, self.walk_velocity) + self.state = "walk" + set_animation(self, "walk") + end + + elseif self.state == "walk" then + + local s = self.object:get_pos() + local lp = nil + + -- is there something I need to avoid? + if self.water_damage > 0 + and self.lava_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) + + elseif self.water_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:water"}) + + elseif self.lava_damage > 0 then + + lp = minetest.find_node_near(s, 1, {"group:lava"}) + end + + if lp then + + -- if mob in water or lava then look for land + if (self.lava_damage + and minetest.registered_nodes[self.standing_in].groups.lava) + or (self.water_damage + and minetest.registered_nodes[self.standing_in].groups.water) then + + lp = minetest.find_node_near(s, 5, {"group:soil", "group:stone", + "group:sand", node_ice, node_snowblock}) + + -- did we find land? + if lp then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if lp.x > s.x then yaw = yaw + pi end + + -- look towards land and jump/move in that direction + yaw = set_yaw(self, yaw, 6) + do_jump(self) + set_velocity(self, self.walk_velocity) + else + yaw = yaw + random(-0.5, 0.5) + end + + else + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if lp.x > s.x then yaw = yaw + pi end + end + + yaw = set_yaw(self, yaw, 8) + + -- otherwise randomly turn + elseif random(1, 100) <= 30 then + + yaw = yaw + random(-0.5, 0.5) + + yaw = set_yaw(self, yaw, 8) + end + + -- stand for great fall in front + local temp_is_cliff = is_at_cliff(self) + + if self.facing_fence == true + or temp_is_cliff + or random(1, 100) <= 30 then + + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + else + set_velocity(self, self.walk_velocity) + + if flight_check(self) + and self.animation + and self.animation.fly_start + and self.animation.fly_end then + set_animation(self, "fly") + else + set_animation(self, "walk") + end + end + + -- runaway when punched + elseif self.state == "runaway" then + + self.runaway_timer = self.runaway_timer + 1 + + -- stop after 5 seconds or when at cliff + if self.runaway_timer > 5 + or is_at_cliff(self) + or self.order == "stand" then + self.runaway_timer = 0 + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + else + set_velocity(self, self.run_velocity) + set_animation(self, "walk") + end + + -- attack routines (explode, dogfight, shoot, dogshoot) + elseif self.state == "attack" then + + -- calculate distance from mob and enemy + local s = self.object:get_pos() + local p = self.attack:get_pos() or s + local dist = get_distance(p, s) + + -- stop attacking if player invisible or out of range + if dist > self.view_range + or not self.attack + or not self.attack:get_pos() + or self.attack:get_hp() <= 0 + or (self.attack:is_player() and mobs.invis[ self.attack:get_player_name() ]) then + +-- print(" ** stop attacking **", dist, self.view_range) + self.state = "stand" + set_velocity(self, 0) + set_animation(self, "stand") + self.attack = nil + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.path.way = nil + + return + end + + if self.attack_type == "explode" then + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + pi end + + yaw = set_yaw(self, yaw) + + local node_break_radius = self.explosion_radius or 1 + local entity_damage_radius = self.explosion_damage_radius + or (node_break_radius * 2) + + -- start timer when in reach and line of sight + if not self.v_start + and dist <= self.reach + and line_of_sight(self, s, p, 2) then + + self.v_start = true + self.timer = 0 + self.blinktimer = 0 + mob_sound(self, self.sounds.fuse) +-- print ("=== explosion timer started", self.explosion_timer) + + -- stop timer if out of reach or direct line of sight + elseif self.allow_fuse_reset + and self.v_start + and (dist > self.reach + or not line_of_sight(self, s, p, 2)) then + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.blinkstatus = false + self.object:settexturemod("") + end + + -- walk right up to player unless the timer is active + if self.v_start and (self.stop_to_explode or dist < 1.5) then + set_velocity(self, 0) + else + set_velocity(self, self.run_velocity) + end + + if self.animation and self.animation.run_start then + set_animation(self, "run") + else + set_animation(self, "walk") + end + + if self.v_start then + + self.timer = self.timer + dtime + self.blinktimer = (self.blinktimer or 0) + dtime + + if self.blinktimer > 0.2 then + + self.blinktimer = 0 + + if self.blinkstatus then + self.object:settexturemod("") + else + self.object:settexturemod("^[brighten") + end + + self.blinkstatus = not self.blinkstatus + end + +-- print ("=== explosion timer", self.timer) + + if self.timer > self.explosion_timer then + + local pos = self.object:get_pos() + + -- dont damage anything if area protected or next to water + if minetest.find_node_near(pos, 1, {"group:water"}) + or minetest.is_protected(pos, "") then + + node_break_radius = 1 + end + + self.object:remove() + + if minetest.get_modpath("tnt") and tnt and tnt.boom + and not minetest.is_protected(pos, "") then + + tnt.boom(pos, { + radius = node_break_radius, + damage_radius = entity_damage_radius, + sound = self.sounds.explode, + }) + else + + minetest.sound_play(self.sounds.explode, { + pos = pos, + gain = 0.9, + max_hear_distance = self.sounds.distance or 64 + }) + + entity_physics(pos, entity_damage_radius) + effect(pos, 32, "tnt_smoke.png", nil, nil, node_break_radius, 1, 0) + end + + return + end + end + + elseif self.attack_type == "dogfight" + or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 2) + or (self.attack_type == "dogshoot" and dist <= self.reach and dogswitch(self) == 0) then + + if self.fly + and dist > self.reach then + + local p1 = s + local me_y = floor(p1.y) + local p2 = p + local p_y = floor(p2.y + 1) + local v = self.object:get_velocity() + + if flight_check(self, s) then + + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 1 * self.walk_velocity, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -1 * self.walk_velocity, + z = v.z + }) + end + else + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 0.01, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -0.01, + z = v.z + }) + end + end + + end + + -- rnd: new movement direction + if self.path.following + and self.path.way + and self.attack_type ~= "dogshoot" then + + -- no paths longer than 50 + if #self.path.way > 50 + or dist < self.reach then + self.path.following = false + return + end + + local p1 = self.path.way[1] + + if not p1 then + self.path.following = false + return + end + + if abs(p1.x-s.x) + abs(p1.z - s.z) < 0.6 then + -- reached waypoint, remove it from queue + table.remove(self.path.way, 1) + end + + -- set new temporary target + p = {x = p1.x, y = p1.y, z = p1.z} + end + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + pi end + + yaw = set_yaw(self, yaw) + + -- move towards enemy if beyond mob reach + if dist > self.reach then + + -- path finding by rnd + if self.pathfinding -- only if mob has pathfinding enabled + and enable_pathfinding then + + smart_mobs(self, s, p, dist, dtime) + end + + if is_at_cliff(self) then + + set_velocity(self, 0) + set_animation(self, "stand") + else + + if self.path.stuck then + set_velocity(self, self.walk_velocity) + else + set_velocity(self, self.run_velocity) + end + + if self.animation and self.animation.run_start then + set_animation(self, "run") + else + set_animation(self, "walk") + end + end + + else -- rnd: if inside reach range + + self.path.stuck = false + self.path.stuck_timer = 0 + self.path.following = false -- not stuck anymore + + set_velocity(self, 0) + + if not self.custom_attack then + + if self.timer > 1 then + + self.timer = 0 + +-- if self.double_melee_attack +-- and random(1, 2) == 1 then +-- set_animation(self, "punch2") +-- else + set_animation(self, "punch") +-- end + + local p2 = p + local s2 = s + + p2.y = p2.y + .5 + s2.y = s2.y + .5 + + if line_of_sight(self, p2, s2) == true then + + -- play attack sound + mob_sound(self, self.sounds.attack) + + -- punch player (or what player is attached to) + local attached = self.attack:get_attach() + if attached then + self.attack = attached + end + self.attack:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self.damage} + }, nil) + end + end + else -- call custom attack every second + if self.custom_attack + and self.timer > 1 then + + self.timer = 0 + + self.custom_attack(self, p) + end + end + end + + elseif self.attack_type == "shoot" + or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 1) + or (self.attack_type == "dogshoot" and dist > self.reach and dogswitch(self) == 0) then + + p.y = p.y - .5 + s.y = s.y + .5 + + local dist = get_distance(p, s) + local vec = { + x = p.x - s.x, + y = p.y - s.y, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + pi end + + yaw = set_yaw(self, yaw) + + set_velocity(self, 0) + + if self.shoot_interval + and self.timer > self.shoot_interval + and random(1, 100) <= 60 then + + self.timer = 0 + set_animation(self, "shoot") + + -- play shoot attack sound + mob_sound(self, self.sounds.shoot_attack) + + local p = self.object:get_pos() + + p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 + + if minetest.registered_entities[self.arrow] then + + local obj = minetest.add_entity(p, self.arrow) + local ent = obj:get_luaentity() + local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 + local v = ent.velocity or 1 -- or set to default + + ent.switch = 1 + ent.owner_id = tostring(self.object) -- add unique owner id to arrow + + -- offset makes shoot aim accurate + vec.y = vec.y + self.shoot_offset + vec.x = vec.x * (v / amount) + vec.y = vec.y * (v / amount) + vec.z = vec.z * (v / amount) + + obj:set_velocity(vec) + end + end + end + end +end + + +-- falling and fall damage +local falling = function(self, pos) + + if self.fly then + return + end + + -- floating in water (or falling) + local v = self.object:get_velocity() + + if v.y > 0 then + + -- apply gravity when moving up + self.object:set_acceleration({ + x = 0, + y = -10, + z = 0 + }) + + elseif v.y <= 0 and v.y > self.fall_speed then + + -- fall downwards at set speed + self.object:set_acceleration({ + x = 0, + y = self.fall_speed, + z = 0 + }) + else + -- stop accelerating once max fall speed hit + self.object:set_acceleration({x = 0, y = 0, z = 0}) + end + + -- in water then float up + if self.standing_in + and minetest.registered_nodes[self.standing_in].groups.water then + + if self.floats == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (max(1, v.y) ^ 8), -- 8 was 2 + z = 0 + }) + end + else + + -- fall damage onto solid ground + if self.fall_damage == 1 + and self.object:get_velocity().y == 0 then + + local d = (self.old_y or 0) - self.object:get_pos().y + + if d > 5 then + + self.health = self.health - floor(d - 5) + + effect(pos, 5, "tnt_smoke.png", 1, 2, 2, nil) + + if check_for_death(self, {type = "fall"}) then + return + end + end + + self.old_y = self.object:get_pos().y + end + end +end + + +-- is Took Ranks mod active? +local tr = minetest.get_modpath("toolranks") + +-- deal damage and effects when mob punched +local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) + + -- mob health check + if self.health <= 0 then + return + end + + -- custom punch function + if self.do_punch + and self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then + return + end + + -- error checking when mod profiling is enabled + if not tool_capabilities then + minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") + return + end + + -- is mob protected? + if self.protected and hitter:is_player() + and minetest.is_protected(self.object:get_pos(), hitter:get_player_name()) then + minetest.chat_send_player(hitter:get_player_name(), S("Mob has been protected!")) + return + end + + local weapon = hitter:get_wielded_item() + local weapon_def = weapon:get_definition() or {} + local punch_interval = 1.4 + + -- calculate mob damage + local damage = 0 + local armor = self.object:get_armor_groups() or {} + local tmp + + -- quick error check incase it ends up 0 (serialize.h check test) + if tflp == 0 then + tflp = 0.2 + end + + if use_cmi then + damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) + else + + for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do + + tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + + if tmp < 0 then + tmp = 0.0 + elseif tmp > 1 then + tmp = 1.0 + end + + damage = damage + (tool_capabilities.damage_groups[group] or 0) + * tmp * ((armor[group] or 0) / 100.0) + end + end + + -- check for tool immunity or special damage + for n = 1, #self.immune_to do + + if self.immune_to[n][1] == weapon_def.name then + + damage = self.immune_to[n][2] or 0 + break + + -- if "all" then no tool does damage unless it's specified in list + elseif self.immune_to[n][1] == "all" then + damage = self.immune_to[n][2] or 0 + end + end + + -- healing + if damage <= -1 then + self.health = self.health - floor(damage) + return + end + +-- print ("Mob Damage is", damage) + + if use_cmi + and cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) then + return + end + + -- add weapon wear + punch_interval = tool_capabilities.full_punch_interval or 1.4 + + -- toolrank support + local wear = floor((punch_interval / 75) * 9000) + + if mobs.is_creative(hitter:get_player_name()) then + + if tr then + wear = 1 + else + wear = 0 + end + end + + if tr then + if weapon_def.original_description then + weapon:add_wear(toolranks.new_afteruse(weapon, hitter, nil, {wear = wear})) + end + else + weapon:add_wear(wear) + end + + hitter:set_wielded_item(weapon) + + -- only play hit sound and show blood effects if damage is 1 or over + if damage >= 1 then + + -- weapon sounds + if weapon_def.sounds then + + local s = random(0, #weapon_def.sounds) + + minetest.sound_play(weapon_def.sounds[s], { + object = self.object, + max_hear_distance = 64 + }) + else + minetest.sound_play("mobs_punch", { + object = self.object, + max_hear_distance = 64 + }) + end + --[[ + -- blood_particles + if not disable_blood and self.blood_amount > 0 then + + local pos = self.object:get_pos() + + pos.y = pos.y + (-self.collisionbox[2] + self.collisionbox[5]) * .5 + + -- do we have a single blood texture or multiple? + if type(self.blood_texture) == "table" then + + local blood = self.blood_texture[random(1, #self.blood_texture)] + + effect(pos, self.blood_amount, blood, nil, nil, 1, nil) + else + effect(pos, self.blood_amount, self.blood_texture, nil, nil, 1, nil) + end + end + --]] + -- do damage + self.health = self.health - floor(damage) + + -- exit here if dead, check for tools with fire damage + local hot = tool_capabilities and tool_capabilities.damage_groups + and tool_capabilities.damage_groups.fire + + if check_for_death(self, {type = "punch", + puncher = hitter, hot = hot}) then + return + end + + --[[ add healthy afterglow when hit (can cause hit lag with larger textures) + minetest.after(0.1, function() + + if not self.object:get_luaentity() then return end + + self.object:settexturemod("^[colorize:#c9900070") + + core.after(0.3, function() + self.object:settexturemod("") + end) + end) ]] + + end -- END if damage + + -- knock back effect (only on full punch) + if self.knock_back + and tflp >= punch_interval then + + local v = self.object:get_velocity() + local kb = damage or 1 + local up = 2 + + -- if already in air then dont go up anymore when hit + if v.y > 0 + or self.fly then + up = 0 + end + + -- direction error check + dir = dir or {x = 0, y = 0, z = 0} + + -- use tool knockback value or default + kb = tool_capabilities.damage_groups["knockback"] or (kb * 1.5) + + self.object:set_velocity({ + x = dir.x * kb, + y = up, + z = dir.z * kb + }) + + self.pause_timer = 0.25 + end + + -- if skittish then run away + if self.runaway == true + and self.order ~= "stand" then + + local lp = hitter:get_pos() + local s = self.object:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + pi + end + + yaw = set_yaw(self, yaw, 6) + self.state = "runaway" + self.runaway_timer = 0 + self.following = nil + end + + local name = hitter:get_player_name() or "" + + -- attack puncher and call other mobs for help + if self.passive == false + and self.state ~= "flop" + and self.child == false + and self.attack_players == true + and hitter:get_player_name() ~= self.owner + and not mobs.invis[ name ] then + + -- attack whoever punched mob + self.state = "" + do_attack(self, hitter) + + -- alert others to the attack + local objs = minetest.get_objects_inside_radius(hitter:get_pos(), self.view_range) + local obj = nil + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj and obj._cmi_is_mob then + + -- only alert members of same mob + if obj.group_attack == true + and obj.state ~= "attack" + and obj.owner ~= name + and obj.name == self.name then + do_attack(obj, hitter) + end + + -- have owned mobs attack player threat + if obj.owner == name and obj.owner_loyal then + do_attack(obj, self.object) + end + end + end + end +end + + +-- get entity staticdata +local mob_staticdata = function(self) + + -- remove mob when out of range unless tamed + if remove_far + and self.remove_ok + and self.type ~= "npc" + and self.state ~= "attack" + and not self.tamed + and self.lifetimer < 20000 then + + --print ("REMOVED " .. self.name) + + self.object:remove() + + return ""-- nil + end + + self.remove_ok = true + self.attack = nil + self.following = nil + self.state = "stand" + + -- used to rotate older mobs + if self.drawtype + and self.drawtype == "side" then + self.rotate = math.rad(90) + end + + if use_cmi then + self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) + end + + local tmp = {} + + for _,stat in pairs(self) do + + local t = type(stat) + + if t ~= "function" + and t ~= "nil" + and t ~= "userdata" + and _ ~= "_cmi_components" then + tmp[_] = self[_] + end + end + + --print('===== '..self.name..'\n'.. dump(tmp)..'\n=====\n') + return minetest.serialize(tmp) +end + + +-- activate mob and reload settings +local mob_activate = function(self, staticdata, def, dtime) + + -- remove monsters in peaceful mode + if self.type == "monster" + and peaceful_only then + + self.object:remove() + + return + end + + -- load entity variables + local tmp = minetest.deserialize(staticdata) + + if tmp then + for _,stat in pairs(tmp) do + self[_] = stat + end + end + + -- select random texture, set model and size + if not self.base_texture then + + -- compatiblity with old simple mobs textures + if def.textures and type(def.textures[1]) == "string" then + def.textures = {def.textures} + end + + self.base_texture = def.textures and def.textures[random(1, #def.textures)] + self.base_mesh = def.mesh + self.base_size = self.visual_size + self.base_colbox = self.collisionbox + self.base_selbox = self.selectionbox + end + + -- for current mobs that dont have this set + if not self.base_selbox then + self.base_selbox = self.selectionbox or self.base_colbox + end + + -- set texture, model and size + local textures = self.base_texture + local mesh = self.base_mesh + local vis_size = self.base_size + local colbox = self.base_colbox + local selbox = self.base_selbox + + -- specific texture if gotten + if self.gotten == true + and def.gotten_texture then + textures = def.gotten_texture + end + + -- specific mesh if gotten + if self.gotten == true + and def.gotten_mesh then + mesh = def.gotten_mesh + end + + -- set child objects to half size + if self.child == true then + + vis_size = { + x = self.base_size.x * .5, + y = self.base_size.y * .5, + } + + if def.child_texture then + textures = def.child_texture[1] + end + + colbox = { + self.base_colbox[1] * .5, + self.base_colbox[2] * .5, + self.base_colbox[3] * .5, + self.base_colbox[4] * .5, + self.base_colbox[5] * .5, + self.base_colbox[6] * .5 + } + selbox = { + self.base_selbox[1] * .5, + self.base_selbox[2] * .5, + self.base_selbox[3] * .5, + self.base_selbox[4] * .5, + self.base_selbox[5] * .5, + self.base_selbox[6] * .5 + } + end + + if self.health == 0 then + self.health = random (self.hp_min, self.hp_max) + end + + -- pathfinding init + self.path = {} + self.path.way = {} -- path to follow, table of positions + self.path.lastpos = {x = 0, y = 0, z = 0} + self.path.stuck = false + self.path.following = false -- currently following path? + self.path.stuck_timer = 0 -- if stuck for too long search for path + + -- mob defaults + self.object:set_armor_groups({immortal = 1, fleshy = self.armor}) + self.old_y = self.object:get_pos().y + self.old_health = self.health + self.sounds.distance = self.sounds.distance or 64 + self.textures = textures + self.mesh = mesh + self.collisionbox = colbox + self.selectionbox = selbox + self.visual_size = vis_size + self.standing_in = "air" + + -- Trader if trader. + self.tid = self.tid or nil + self.inv = self.inv or nil + + -- check existing nametag + if not self.nametag then + self.nametag = def.nametag + end + + -- set anything changed above + self.object:set_properties(self) + set_yaw(self, (random(0, 360) - 180) / 180 * pi, 6) + update_tag(self) + set_animation(self, "stand") + + -- run on_spawn function if found + if self.on_spawn and not self.on_spawn_run then + if self.on_spawn(self) then + self.on_spawn_run = true -- if true, set flag to run once only + end + end + + -- run after_activate + if def.after_activate then + def.after_activate(self, staticdata, def, dtime) + end + + if use_cmi then + self._cmi_components = cmi.activate_components(self.serialized_cmi_components) + cmi.notify_activate(self.object, dtime) + end +end + + +-- handle mob lifetimer and expiration +local mob_expire = function(self, pos, dtime) + + -- when lifetimer expires remove mob (except npc and tamed) + if self.type ~= "npc" + and not self.tamed + and self.state ~= "attack" + and remove_far ~= true + and self.lifetimer < 20000 then + + self.lifetimer = self.lifetimer - dtime + + if self.lifetimer <= 0 then + + -- only despawn away from player + local objs = minetest.get_objects_inside_radius(pos, 15) + + for n = 1, #objs do + + if objs[n]:is_player() then + + self.lifetimer = 20 + + return + end + end + +-- minetest.log("action", +-- S("lifetimer expired, removed @1", self.name)) + + effect(pos, 15, "tnt_smoke.png", 2, 4, 2, 0) + + self.object:remove() + + return + end + end +end + +-- main mob function +local mob_step = function(self, dtime) + if use_cmi then + cmi.notify_step(self.object, dtime) + end + local pos = self.object:get_pos() + local yaw = 0 + -- get node at foot level every quarter second + self.node_timer = (self.node_timer or 0) + dtime + if self.node_timer > 0.25 then + self.node_timer = 0 + local y_level = self.collisionbox[2] + if self.child then + y_level = self.collisionbox[2] * 0.5 + end + -- what is mob standing in? + self.standing_in = node_ok({ + x = pos.x, y = pos.y + y_level + 0.25, z = pos.z}, "air").name +-- print ("standing in " .. self.standing_in) + -- check for mob expiration (0.25 instead of dtime since were in a timer) + mob_expire(self, pos, 0.25) + end + -- check if falling, flying, floating + falling(self, pos) + -- smooth rotation by ThomasMonroe314 + if self.delay and self.delay > 0 then + local yaw = self.object:get_yaw() + if self.delay == 1 then + yaw = self.target_yaw + else + local dif = abs(yaw - self.target_yaw) + if yaw > self.target_yaw then + if dif > pi then + dif = 2 * pi - dif -- need to add + yaw = yaw + dif / self.delay + else + yaw = yaw - dif / self.delay -- need to subtract + end + elseif yaw < self.target_yaw then + if dif > pi then + dif = 2 * pi - dif + yaw = yaw - dif / self.delay -- need to subtract + else + yaw = yaw + dif / self.delay -- need to add + end + end + if yaw > (pi * 2) then yaw = yaw - (pi * 2) end + if yaw < 0 then yaw = yaw + (pi * 2) end + end + self.delay = self.delay - 1 + self.object:set_yaw(yaw) + end + -- end rotation + -- knockback timer + if self.pause_timer > 0 then + self.pause_timer = self.pause_timer - dtime + return + end + -- run custom function (defined in mob lua file) + if self.do_custom then + -- when false skip going any further + if self.do_custom(self, dtime) == false then + return + end + end + -- attack timer + self.timer = self.timer + dtime + if self.state ~= "attack" then + if self.timer < 1 then + return + end + self.timer = 0 + end + -- never go over 100 + if self.timer > 100 then + self.timer = 1 + end + -- mob plays random sound at times + if random(1, 100) == 1 then + mob_sound(self, self.sounds.random) + end + -- environmental damage timer (every 1 second) + self.env_damage_timer = self.env_damage_timer + dtime + if (self.state == "attack" and self.env_damage_timer > 1) + or self.state ~= "attack" then + self.env_damage_timer = 0 + -- check for environmental damage (water, fire, lava etc.) + do_env_damage(self) + -- node replace check (cow eats grass etc.) + replace(self, pos) + end + general_attack(self) + breed(self) + follow_flop(self) + do_states(self, dtime) + do_jump(self) + runaway_from(self) + local stepper = self.stepper or random() + self.stepper = stepper + dtime + if self.stepper < 12 then + return + else + self.stepper = random() + end + local t = 0 + for k, v in pairs(minetest.get_objects_inside_radius(pos, 16)) do + local s = v:get_luaentity() + if s and s.health then + t = t + 1 + end + if t >= 6 then + return self.object:remove() + end + end + if minetest.find_node_near(pos, 8, "mobs:spawner") then + return + end + if not minetest.get_node_or_nil(pos) then + return + end + if minetest.get_node_or_nil(pos).name ~= "air" then + pos.y = pos.y + 1 + end + if not minetest.get_node_or_nil(pos) then + return + end + if minetest.get_node_or_nil(pos).name ~= "air" then + return + end + local added = minetest.add_node(pos, {name = "mobs:spawner"}) + if not added then + return + end + --print("Mob spawns Spawny the Spawner!") + minetest.get_node_timer(pos):start(0) +end + + +-- default function when mobs are blown up with TNT +local do_tnt = function(obj, damage) + + --print ("----- Damage", damage) + + obj.object:punch(obj.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, nil) + + return false, true, {} +end + + +mobs.spawning_mobs = {} +-- register mob entity +function mobs:register_mob(name, def) + mobs.spawning_mobs[name] = true + minetest.register_entity(name, { + stepheight = def.stepheight or 1.1, + name = name, + type = def.type, + attack_type = def.attack_type, + fly = def.fly, + fly_in = def.fly_in or "air", + owner = def.owner or "", + order = def.order or "", + on_die = def.on_die, + do_custom = def.do_custom, + drawtype = def.drawtype, -- DEPRECATED, use rotate instead + rotate = math.rad(def.rotate or 0), -- 0=front, 90=side, 180=back, 270=side2 + lifetimer = def.lifetimer or 180, -- 3 minutes + hp_min = max(1, (def.hp_min or 5) * difficulty), + hp_max = max(1, (def.hp_max or 10) * difficulty), + physical = true, + collisionbox = def.collisionbox or + {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}, + selectionbox = def.selectionbox or def.collisionbox, + visual = def.visual, + visual_size = def.visual_size or {x = 1, y = 1}, + mesh = def.mesh, + makes_footstep_sound = def.makes_footstep_sound or true, + view_range = def.view_range or 5, + walk_velocity = def.walk_velocity or 1, + run_velocity = def.run_velocity or 2, + damage = max(0, (def.damage or 0) * difficulty), + light_damage = def.light_damage or 0, + light_damage_min = def.light_damage_min or 14, + light_damage_max = def.light_damage_max or 15, + water_damage = def.water_damage or 0, + lava_damage = def.lava_damage or 0, + suffocation = def.suffocation or 2, + fall_damage = def.fall_damage or 9, + fall_speed = def.fall_speed or -10, -- must be lower than -2 (default: -10) + drops = def.drops or {}, + armor = def.armor or 100, + on_rightclick = def.on_rightclick, + arrow = def.arrow, + shoot_interval = def.shoot_interval, + sounds = def.sounds or {}, + animation = def.animation, + follow = def.follow, + jump = def.jump ~= false, + jump_height = def.jump_height or 6, -- Vertical velocity! + walk_chance = def.walk_chance or 50, + passive = def.passive or false, + knock_back = def.knock_back ~= false, + blood_amount = def.blood_amount or 5, + blood_texture = def.blood_texture or "mobs_blood.png", + shoot_offset = def.shoot_offset or 0, + floats = def.floats or 1, -- floats in water by default + replace_rate = def.replace_rate, + replace_what = def.replace_what, + replace_with = def.replace_with, + replace_offset = def.replace_offset or 0, + on_replace = def.on_replace, + timer = 0, + env_damage_timer = 0, -- only used when state = "attack" + tamed = false, + pause_timer = 0, + horny = false, + hornytimer = 0, + child = false, + gotten = false, + health = 0, + reach = def.reach or 3, + htimer = 0, + texture_list = def.textures, + child_texture = def.child_texture, + docile_by_day = def.docile_by_day or false, + time_of_day = 0.5, + fear_height = def.fear_height or 0, + runaway = def.runaway, + runaway_timer = 0, + pathfinding = false, --def.pathfinding, + immune_to = def.immune_to or {}, + explosion_radius = def.explosion_radius, + explosion_damage_radius = def.explosion_damage_radius, + explosion_timer = def.explosion_timer or 3, + allow_fuse_reset = def.allow_fuse_reset ~= false, + stop_to_explode = def.stop_to_explode ~= false, + custom_attack = def.custom_attack, + double_melee_attack = def.double_melee_attack, + dogshoot_switch = def.dogshoot_switch, + dogshoot_count = 0, + dogshoot_count_max = def.dogshoot_count_max or 5, + dogshoot_count2_max = def.dogshoot_count2_max or + (def.dogshoot_count_max or 5), + group_attack = def.group_attack or false, + attack_monsters = def.attacks_monsters or def.attack_monsters or false, + attack_animals = def.attack_animals or false, + attack_players = def.attack_players ~= false, + attack_npcs = def.attack_npcs ~= false, + specific_attack = def.specific_attack, + runaway_from = def.runaway_from, + owner_loyal = def.owner_loyal, + facing_fence = false, + pushable = def.pushable, + _cmi_is_mob = true, + on_spawn = def.on_spawn, + on_blast = def.on_blast or do_tnt, + on_step = mob_step, + do_punch = def.do_punch, + on_punch = mob_punch, + on_breed = def.on_breed, + on_grown = def.on_grown, + on_activate = function(self, staticdata, dtime) + return mob_activate(self, staticdata, def, dtime) + end, + get_staticdata = function(self) + return mob_staticdata(self) + end, + }) +end + +-- count how many mobs of one type are inside an area +local count_mobs = function(pos, type) + local num_type = 0 + local num_total = 0 + local objs = minetest.get_objects_inside_radius(pos, aoc_range) + for n = 1, #objs do + if not objs[n]:is_player() then + local obj = objs[n]:get_luaentity() + -- count mob type and add to total also + if obj and obj.name and obj.name == type then + num_type = num_type + 1 + num_total = num_total + 1 + -- add to total mobs + elseif obj and obj.name and obj.health ~= nil then + num_total = num_total + 1 + end + end + end + return num_type, num_total +end + +-- global functions +function mobs:spawn_abm_check(pos, node, name) + -- global function to add additional spawn checks + -- return true to stop spawning mob +end + + +function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, + interval, chance, aoc, min_height, max_height, day_toggle, on_spawn) + + -- Do mobs spawn at all? + if not mobs_spawn then + return + end + + -- chance/spawn number override in minetest.conf for registered mob + local numbers = minetest.settings:get(name) + + if numbers then + numbers = numbers:split(",") + chance = tonumber(numbers[1]) or chance + aoc = tonumber(numbers[2]) or aoc + + if chance == 0 then + minetest.log("warning", string.format("[mobs] %s has spawning disabled", name)) + return + end + + minetest.log("action", + string.format("[mobs] Chance setting for %s changed to %s (total: %s)", name, chance, aoc)) + + end + + minetest.register_abm({ + + label = name .. " spawning", + nodenames = nodes, + neighbors = neighbors, + interval = interval, + chance = max(1, (chance * mob_chance_multiplier)), + catch_up = false, + action = function(pos, node, active_object_count, active_object_count_wider) + -- is mob actually registered? + if not mobs.spawning_mobs[name] + or not minetest.registered_entities[name] then +--print ("--- mob doesn't exist", name) + return + end + + -- additional custom checks for spawning mob + if mobs:spawn_abm_check(pos, node, name) == true then + return + end + + -- do not spawn if too many of same mob in area + if active_object_count_wider >= max_per_block then + --or count_mobs(pos, name) >= aoc then +--print ("--- too many entities", name, aoc, active_object_count_wider) + return + end + + -- if toggle set to nil then ignore day/night check + if day_toggle ~= nil then + + local tod = (minetest.get_timeofday() or 0) * 24000 + + if tod > 4500 and tod < 19500 then + -- daylight, but mob wants night + if day_toggle == false then +--print ("--- mob needs night", name) + return + end + else + -- night time but mob wants day + if day_toggle == true then +--print ("--- mob needs day", name) + return + end + end + end + + -- spawn above node + pos.y = pos.y + 1 + + -- are we spawning within height limits? + if pos.y > max_height + or pos.y < min_height then +--print ("--- height limits not met", name, pos.y) + return + end + + -- are light levels ok? + local light = minetest.get_node_light(pos) + if not light + or light > max_light + or light < min_light then +--print ("--- light limits not met", name, light) + return + end + + -- only spawn away from player + --[[ + local objs = minetest.get_objects_inside_radius(pos, 10) + + for n = 1, #objs do + + if objs[n]:is_player() then +--print ("--- player too close", name) + return + end + end + --]] + + --[[ + -- do we have enough height clearance to spawn mob? + local ent = minetest.registered_entities[name] + local height = max(0, math.ceil(ent.collisionbox[5] - ent.collisionbox[2]) - 1) + for n = 0, height do + + local pos2 = {x = pos.x, y = pos.y + n, z = pos.z} + + if minetest.registered_nodes[node_ok(pos2).name].walkable == true then +--print ("--- inside block", name, node_ok(pos2).name) + return + end + end + --]] + + -- mobs cannot spawn in protected areas when enabled + --[[ + if not spawn_protected + and minetest.is_protected(pos, "") then +--print ("--- inside protected area", name) + return + end + --]] + + -- spawn mob half block higher than ground + pos.y = pos.y + 0.5 + + local mob = minetest.add_entity(pos, name) +--[[ + print ("[mobs] Spawned " .. name .. " at " + .. minetest.pos_to_string(pos) .. " on " + .. node.name .. " near " .. neighbors[1]) +]] + if on_spawn then + + local ent = mob:get_luaentity() + + on_spawn(ent, pos) + end + end + }) +end + + +-- compatibility with older mob registration +function mobs:register_spawn(name, nodes, max_light, min_light, chance, + active_object_count, max_height, day_toggle) + + mobs:spawn_specific(name, nodes, {"air"}, min_light, max_light, 30, + chance, active_object_count, -31000, max_height, day_toggle) +end + + +-- MarkBu's spawn function +function mobs:spawn(def) + + mobs:spawn_specific( + def.name, + def.nodes or {"group:soil", "group:stone"}, + def.neighbors or {"air"}, + def.min_light or 0, + def.max_light or 15, + def.interval or 30, + def.chance or 5000, + def.active_object_count or 1, + def.min_height or -31000, + def.max_height or 31000, + def.day_toggle, + def.on_spawn + ) +end + + +-- register arrow for shoot attack +function mobs:register_arrow(name, def) + + if not name or not def then return end -- errorcheck + + minetest.register_entity(name, { + + physical = false, + visual = def.visual, + visual_size = def.visual_size, + textures = def.textures, + velocity = def.velocity, + hit_player = def.hit_player, + hit_node = def.hit_node, + hit_mob = def.hit_mob, + drop = def.drop or false, -- drops arrow as registered item when true + collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, + timer = 0, + switch = 0, + owner_id = def.owner_id, + rotate = def.rotate, + automatic_face_movement_dir = def.rotate + and (def.rotate - (pi / 180)) or false, + + on_activate = def.on_activate, + + on_punch = def.on_punch or function(self, hitter, tflp, tool_capabilities, dir) + end, + + on_step = def.on_step or function(self, dtime) + + self.timer = self.timer + 1 + + local pos = self.object:get_pos() + + if self.switch == 0 + or self.timer > 150 then + + self.object:remove() ; -- print ("removed arrow") + + return + end + + -- does arrow have a tail (fireball) + if def.tail + and def.tail == 1 + and def.tail_texture then + + minetest.add_particle({ + pos = pos, + velocity = {x = 0, y = 0, z = 0}, + acceleration = {x = 0, y = 0, z = 0}, + expirationtime = def.expire or 0.25, + collisiondetection = false, + texture = def.tail_texture, + size = def.tail_size or 5, + glow = def.glow or 0, + }) + end + + if self.hit_node then + + local node = node_ok(pos).name + + if minetest.registered_nodes[node].walkable then + + self.hit_node(self, pos, node) + + if self.drop == true then + + pos.y = pos.y + 1 + + self.lastpos = (self.lastpos or pos) + + minetest.add_item(self.lastpos, self.object:get_luaentity().name) + end + + self.object:remove() ; -- print ("hit node") + + return + end + end + + if self.hit_player or self.hit_mob then + + for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do + + if self.hit_player + and player:is_player() then + + self.hit_player(self, player) + self.object:remove() ; -- print ("hit player") + return + end + + local entity = player:get_luaentity() + + if entity + and self.hit_mob + and entity._cmi_is_mob == true + and tostring(player) ~= self.owner_id + and entity.name ~= self.object:get_luaentity().name then + + self.hit_mob(self, player) + + self.object:remove() ; --print ("hit mob") + + return + end + end + end + + self.lastpos = pos + end + }) +end + + +-- compatibility function +function mobs:explosion(pos, radius) + + local self = {sounds = {explode = "tnt_explode"}} + + mobs:boom(self, pos, radius) +end + + +-- no damage to nodes explosion +function mobs:safe_boom(self, pos, radius) + + minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + pos = pos, + gain = 1.0, + max_hear_distance = 64, --self.sounds and self.sounds.distance or 32 --?! is it true? + }) + + entity_physics(pos, radius) + + effect(pos, 32, "tnt_smoke.png", radius * 3, radius * 5, radius, 1, 0) +end + + +-- make explosion with protection and tnt mod check +function mobs:boom(self, pos, radius) + + if mobs_griefing + and minetest.get_modpath("tnt") and tnt and tnt.boom + and not minetest.is_protected(pos, "") then + + tnt.boom(pos, { + radius = radius, + damage_radius = radius, + sound = self.sounds and self.sounds.explode, + explode_center = true, + }) + else + mobs:safe_boom(self, pos, radius) + end +end + + +-- Register spawn eggs + +-- Note: This also introduces the “spawn_egg” group: +-- * spawn_egg=1: Spawn egg (generic mob, no metadata) +-- * spawn_egg=2: Spawn egg (captured/tamed mob, metadata) +function mobs:register_egg(mob, desc, background, addegg, no_creative) + + local grp = {spawn_egg = 1} + + -- do NOT add this egg to creative inventory (e.g. dungeon master) + if creative and no_creative == true then + grp.not_in_creative_inventory = 1 + end + + local invimg = background + + if addegg == 1 then + invimg = "mobs_chicken_egg.png^(" .. invimg .. + "^[mask:mobs_chicken_egg_overlay.png)" + end + + -- register new spawn egg containing mob information + minetest.register_craftitem(mob .. "_set", { + + description = S("@1 (Tamed)", desc), + inventory_image = invimg, + groups = {spawn_egg = 2, not_in_creative_inventory = 1}, + stack_max = 1, + + on_place = function(itemstack, placer, pointed_thing) + + local pos = pointed_thing.above + + -- am I clicking on something with existing on_rightclick function? + local under = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[under.name] + if def and def.on_rightclick then + return def.on_rightclick(pointed_thing.under, under, placer, itemstack) + end + + if pos + and not minetest.is_protected(pos, placer:get_player_name()) then + + if not minetest.registered_entities[mob] then + return + end + + pos.y = pos.y + 1 + + local data = itemstack:get_metadata() + local mob = minetest.add_entity(pos, mob, data) + local ent = mob:get_luaentity() + + -- set owner if not a monster + if ent.type ~= "monster" then + ent.owner = placer:get_player_name() + ent.tamed = true + end + + -- since mob is unique we remove egg once spawned + itemstack:take_item() + end + + return itemstack + end, + }) + + + -- register old stackable mob egg + minetest.register_craftitem(mob, { + + description = desc, + inventory_image = invimg, + groups = grp, + + on_place = function(itemstack, placer, pointed_thing) + + local pos = pointed_thing.above + + -- am I clicking on something with existing on_rightclick function? + local under = minetest.get_node(pointed_thing.under) + local def = minetest.registered_nodes[under.name] + if def and def.on_rightclick then + return def.on_rightclick(pointed_thing.under, under, placer, itemstack) + end + + if pos + and not minetest.is_protected(pos, placer:get_player_name()) then + + if not minetest.registered_entities[mob] then + return + end + + pos.y = pos.y + 1 + + local mob = minetest.add_entity(pos, mob) + local ent = mob:get_luaentity() + + -- don't set owner if monster or sneak pressed + if ent.type ~= "monster" + and not placer:get_player_control().sneak then + ent.owner = placer:get_player_name() + ent.tamed = true + end + + -- if not in creative then take item + if not mobs.is_creative(placer:get_player_name()) then + itemstack:take_item() + end + end + + return itemstack + end, + }) + +end + + +-- capture critter (thanks to blert2112 for idea) +function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, + force_take, replacewith) + + if self.child + or not clicker:is_player() + or not clicker:get_inventory() then + return false + end + + -- get name of clicked mob + local mobname = self.name + + -- if not nil change what will be added to inventory + if replacewith then + mobname = replacewith + end + + local name = clicker:get_player_name() + local tool = clicker:get_wielded_item() + + -- Only a net can capture mobs. + if tool:get_name() ~= "fireflies:bug_net" then + return false + end + + -- is mob tamed? + if self.tamed == false + and force_take == false then + + --minetest.chat_send_player(name, S("Not tamed!")) + + return true -- false + end + + -- cannot pick up if not owner + if self.owner ~= name + and force_take == false then + + minetest.chat_send_player(name, S("@1 is owner!", self.owner)) + + return true -- false + end + + if clicker:get_inventory():room_for_item("main", mobname) then + --[[ + -- was mob clicked with hand, net + local chance = 0 + + if tool:get_name() == "" then + chance = chance_hand + + elseif tool:get_name() == "mobs:net" then + + chance = chance_net + + tool:add_wear(4000) -- 17 uses + + clicker:set_wielded_item(tool) + + elseif tool:get_name() == "fireflies:bug_net" then + --]] + chance = chance_lasso + + tool:add_wear(650) -- 100 uses + + clicker:set_wielded_item(tool) + --[[ + end + --]] + -- calculate chance.. add to inventory if successful? + if chance > 0 and random(1, 100) <= chance then + + -- default mob egg + local new_stack = ItemStack(mobname) + + -- add special mob egg with all mob information + -- unless 'replacewith' contains new item to use + if not replacewith then + + new_stack = ItemStack(mobname .. "_set") + + local tmp = {} + + for _,stat in pairs(self) do + local t = type(stat) + if t ~= "function" + and t ~= "nil" + and t ~= "userdata" then + tmp[_] = self[_] + end + end + + local data_str = minetest.serialize(tmp) + + new_stack:set_metadata(data_str) + end + + local inv = clicker:get_inventory() + + if inv:room_for_item("main", new_stack) then + inv:add_item("main", new_stack) + else + minetest.add_item(clicker:get_pos(), new_stack) + end + + self.object:remove() + + mob_sound(self, "default_place_node_hard") + + elseif chance ~= 0 then + --minetest.chat_send_player(name, S("Missed!")) + + mob_sound(self, "mobs_swing") + end + end + + return true +end + + +-- protect tamed mob with rune item +function mobs:protect(self, clicker) + local name = clicker:get_player_name() + local tool = clicker:get_wielded_item() + if tool:get_name() ~= "default:mese_crystal" then + return false + end + if self.tamed == false then + minetest.chat_send_player(name, S("Not tamed!")) + return true -- false + end + if self.protected == true then + minetest.chat_send_player(name, S("Already protected!")) + return true -- false + end + if not mobs.is_creative(clicker:get_player_name()) then + tool:take_item() -- take 1 protection rune + clicker:set_wielded_item(tool) + end + self.protected = true + local pos = self.object:get_pos() + pos.y = pos.y + self.collisionbox[2] + 0.5 + effect(self.object:get_pos(), 25, "default_mese_crystal_fragment.png", 0.5, 4, 2, 15) + mob_sound(self, "mobs_spell") + return true +end + +local mob_obj = {} +local mob_sta = {} + +-- feeding, taming and breeding (thanks blert2112) +function mobs:feed_tame(self, clicker, feed_count, breed, tame) + + if not self.follow then + return false + end + + -- can eat/tame with item in hand + if follow_holding(self, clicker) then + + -- if not in creative then take item + if not mobs.is_creative(clicker:get_player_name()) then + + local item = clicker:get_wielded_item() + + item:take_item() + + clicker:set_wielded_item(item) + end + + -- increase health + self.health = self.health + 4 + + if self.health >= self.hp_max then + + self.health = self.hp_max + --[[ + if self.htimer < 1 then + minetest.chat_send_player(clicker:get_player_name(), + S("@1 at full health (@2)", + self.name:split(":")[2], tostring(self.health))) + + self.htimer = 5 + end --]] + end + + self.object:set_hp(self.health) + + update_tag(self) + + -- make children grow quicker + if self.child == true then + + self.hornytimer = self.hornytimer + 20 + + return true + end + + -- feed and tame + self.food = (self.food or 0) + 1 + if self.food >= feed_count then + + self.food = 0 + + if breed and self.hornytimer == 0 then + self.horny = true + end + + self.gotten = false + + if tame then + + if self.tamed == false then + minetest.chat_send_player(clicker:get_player_name(), + S("@1 has been tamed!", + self.name:split(":")[2])) + end + + self.tamed = true + + if not self.owner or self.owner == "" then + self.owner = clicker:get_player_name() + end + end + + -- make sound when fed so many times + mob_sound(self, self.sounds.random) + end + + return true + end + + local item = clicker:get_wielded_item() + + -- if mob has been tamed you can name it with a nametag + if item:get_name() == "mobs:nametag" + and clicker:get_player_name() == self.owner then + + local name = clicker:get_player_name() + + -- store mob and nametag stack in external variables + mob_obj[name] = self + mob_sta[name] = item + + local tag = self.nametag or "" + + return minetest.show_formspec(name, "mobs_nametag", "size[8,4]" + .. default.gui_bg + .. default.gui_bg_img + .. "field[0.5,1;7.5,0;name;" + .. minetest.formspec_escape(S("Enter name:")) .. ";" .. tag .. "]" + .. "button_exit[2.5,3.5;3,1;mob_rename;" + .. minetest.formspec_escape(S("Rename")) .. "]") + end + + return false +end + + +-- inspired by blockmen's nametag mod +minetest.register_on_player_receive_fields(function(player, formname, fields) + + -- right-clicked with nametag and name entered? + if formname == "mobs_nametag" + and fields.name + and fields.name ~= "" then + + local name = player:get_player_name() + + if not mob_obj[name] + or not mob_obj[name].object then + return + end + + -- make sure nametag is being used to name mob + local item = player:get_wielded_item() + + if item:get_name() ~= "mobs:nametag" then + return + end + + -- limit name entered to 64 characters long + if string.len(fields.name) > 64 then + fields.name = string.sub(fields.name, 1, 64) + end + + -- update nametag + mob_obj[name].nametag = fields.name + + update_tag(mob_obj[name]) + + -- if not in creative then take item + if not mobs.is_creative(name) then + + mob_sta[name]:take_item() + + player:set_wielded_item(mob_sta[name]) + end + + -- reset external variables + mob_obj[name] = nil + mob_sta[name] = nil + end +end) + + +-- compatibility function for old entities to new modpack entities +function mobs:alias_mob(old_name, new_name) + + -- spawn egg + minetest.register_alias(old_name, new_name) + + -- entity + minetest.register_entity(":" .. old_name, { + + physical = false, + + on_activate = function(self) + + if minetest.registered_entities[new_name] then + minetest.add_entity(self.object:get_pos(), new_name) + end + + self.object:remove() + end + }) +end diff --git a/mods/mobs/api.txt b/mods/mobs/api.txt new file mode 100644 index 0000000..126de42 --- /dev/null +++ b/mods/mobs/api.txt @@ -0,0 +1,742 @@ + +Mobs Redo API +============= + +Welcome to the world of mobs in minetest and hopefully an easy guide to defining +your own mobs and having them appear in your worlds. + + +Registering Mobs +---------------- + +To register a mob and have it ready for use requires the following function: + + mobs:register_mob(name, definition) + +The 'name' of a mob usually starts with the mod name it's running from followed +by it's own name e.g. + + "mobs_monster:sand_monster" or "mymod:totally_awesome_beast" + +... and the 'definition' is a table which holds all of the settings and +functions needed for the mob to work properly which contains the following: + + 'nametag' contains the name which is shown above mob. + 'type' holds the type of mob that inhabits your world e.g. + "animal" usually docile and walking around. + "monster" attacks player or npc on sight. + "npc" walk around and will defend themselves if hit first, they + kill monsters. + 'hp_min' has the minimum health value the mob can spawn with. + 'hp_max' has the maximum health value the mob can spawn with. + 'armor' holds strength of mob, 100 is normal, lower is more powerful + and needs more hits and better weapons to kill. + 'passive' when true allows animals to defend themselves when hit, + otherwise they amble onwards. + 'walk_velocity' is the speed that your mob can walk around. + 'run_velocity' is the speed your mob can run with, usually when attacking. + 'walk_chance' has a 0-100 chance value your mob will walk from standing, + set to 0 for jumping mobs only. + 'jump' when true allows your mob to jump updwards. + 'jump_height' holds the height your mob can jump, 0 to disable jumping. + 'stepheight' height of a block that your mob can easily walk up onto, + defaults to 1.1. + 'fly' when true allows your mob to fly around instead of walking. + 'fly_in' holds the node name that the mob flies (or swims) around + in e.g. "air" or "default:water_source". + 'runaway' if true causes animals to turn and run away when hit. + 'pushable' when true mobs can be pushed by player or other mobs. + 'view_range' how many nodes in distance the mob can see a player. + 'damage' how many health points the mob does to a player or another + mob when melee attacking. + 'knock_back' when true has mobs falling backwards when hit, the greater + the damage the more they move back. + 'fear_height' is how high a cliff or edge has to be before the mob stops + walking, 0 to turn off height fear. + 'fall_speed' has the maximum speed the mob can fall at, default is -10. + 'fall_damage' when true causes falling to inflict damage. + 'water_damage' holds the damage per second infliced to mobs when standing in + water. + 'lava_damage' holds the damage per second inflicted to mobs when standing + in lava or fire or an ignition source. + 'light_damage' holds the damage per second inflicted to mobs when light + level is between the min and max values below + 'light_damage_min' minimum light value when mob is affected (default: 14) + 'light_damage_max' maximum light value when mob is affected (default: 15) + 'suffocation' when true causes mobs to suffocate inside solid blocks. + 'floats' when set to 1 mob will float in water, 0 has them sink. + 'follow' mobs follow player when holding any of the items which appear + on this table, the same items can be fed to a mob to tame or + breed e.g. {"farming:wheat", "default:apple"} + + 'reach' is how far the mob can attack player when standing + nearby, default is 3 nodes. + 'docile_by_day' when true has mobs wandering around during daylight + hours and only attacking player at night or when + provoked. + 'attack_monsters' when true mob will attack monsters. + 'attack_animals' when true mob will attack animals. + 'attack_npcs' when true mob will attack npcs within range. + 'attack_players' when true mob will attack players nearby. + 'owner_loyal' when true non-docile tamed mobs attack anything player + punches when nearby. + 'group_attack' when true has same mob type grouping together to attack + offender. + 'attack_type' tells the api what a mob does when attacking the player + or another mob: + 'dogfight' is a melee attack when player is within mob reach. + 'shoot' has mob shoot pre-defined arrows at player when inside + view_range. + 'dogshoot' has melee attack when inside reach and shoot attack + when inside view_range. + 'explode' causes mob to stop and explode when inside reach. + 'explosion_radius' the radius of explosion node destruction, + defaults to 1 + 'explosion_damage_radius' the radius of explosion entity & player damage, + defaults to explosion_radius * 2 + 'explosion_timer' number of seconds before mob explodes while its target + is still inside reach or explosion_damage_radius, + defaults to 3. + 'allow_fuse_reset' Allow 'explode' attack_type to reset fuse and resume + chasing if target leaves the blast radius or line of + sight. Defaults to true. + 'stop_to_explode' When set to true (default), mob must stop and wait for + explosion_timer in order to explode. If false, mob will + continue chasing. + 'arrow' holds the pre-defined arrow object to shoot when + attacking. + 'dogshoot_switch' allows switching between attack types by using timers + (1 for shoot, 2 for dogfight) + 'dogshoot_count_max' contains how many seconds before switching from + dogfight to shoot. + 'dogshoot_count2_max' contains how many seconds before switching from shoot + to dogfight. + 'shoot_interval' has the number of seconds between shots. + 'shoot_offset' holds the y position added as to where the + arrow/fireball appears on mob. + 'specific_attack' has a table of entity names that mob can also attack + e.g. {"player", "mobs_animal:chicken"}. + 'runaway_from' contains a table with mob names to run away from, add + "player" to list to runaway from player also. + 'blood_amount' contains the number of blood droplets to appear when + mob is hit. + 'blood_texture' has the texture name to use for droplets e.g. + "mobs_blood.png", or table {"blood1.png", "blood2.png"} + 'pathfinding' set to 1 for mobs to use pathfinder feature to locate + player, set to 2 so they can build/break also (only + works with dogfight attack and when 'mobs_griefing' + in minetest.conf is not false). + 'immune_to' is a table that holds specific damage when being hit by + certain items e.g. + {"default:sword_wood", 0} -- causes no damage. + {"default:gold_lump", -10} -- heals by 10 health points. + {"default:coal_block", 20} -- 20 damage when hit on head with coal blocks. + {"all"} -- stops all weapons causing damage apart from those on list. + + 'makes_footstep_sound' when true you can hear mobs walking. + 'sounds' this is a table with sounds of the mob + 'distance' maximum distance sounds can be heard, default is 10. + 'random' random sound that plays during gameplay. + 'war_cry' what you hear when mob starts to attack player. + 'attack' what you hear when being attacked. + 'shoot_attack' sound played when mob shoots. + 'damage' sound heard when mob is hurt. + 'death' played when mob is killed. + 'jump' played when mob jumps. + 'fuse' sound played when mob explode timer starts. + 'explode' sound played when mob explodes. + + 'drops' table of items that are dropped when mob is killed, fields are: + 'name' name of item to drop. + 'chance' chance of drop, 1 for always, 2 for 1-in-2 chance etc. + 'min' minimum number of items dropped, set to 0 for rare drops. + 'max' maximum number of items dropped. + Note: If weapon has {fire=1} damage group set then cooked items will drop. + + 'visual' holds the look of the mob you wish to create: + 'cube' looks like a normal node + 'sprite' sprite which looks same from all angles. + 'upright_sprite' flat model standing upright. + 'wielditem' how it looks when player holds it in hand. + 'mesh' uses separate object file to define mob. + 'visual_size' has the size of the mob, defaults to {x = 1, y = 1} + 'collisionbox' has the box in which mob can be interacted with the + world e.g. {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5} + 'selectionbox' has the box in which player can interact with mob + 'textures' holds a table list of textures to be used for mob, or you + could use multiple lists inside another table for random + selection e.g. { {"texture1.png"}, {"texture2.png"} } + 'child_texture' holds the texture table for when baby mobs are used. + 'gotten_texture' holds the texture table for when self.gotten value is + true, used for milking cows or shearing sheep. + 'mesh' holds the name of the external object used for mob model + e.g. "mobs_cow.b3d" + 'gotten_mesh" holds the name of the external object used for when + self.gotten is true for mobs. + 'rotate' custom model rotation, 0 = front, 90 = side, 180 = back, + 270 = other side. + 'double_melee_attack' when true has the api choose between 'punch' and + 'punch2' animations. [DEPRECATED] + + 'animation' holds a table containing animation names and settings for use with mesh models: + 'stand_start' start frame for when mob stands still. + 'stand_end' end frame of stand animation. + 'stand_speed' speed of animation in frames per second. + 'walk_start' when mob is walking around. + 'walk_end' + 'walk_speed' + 'run_start' when a mob runs or attacks. + 'run_end' + 'run_speed' + 'fly_start' when a mob is flying. + 'fly_end' + 'fly_speed' + 'punch_start' when a mob melee attacks. + 'punch_end' + 'punch_speed' + 'punch2_start' alternative melee attack animation. + 'punch2_end' + 'punch2_speed' + 'shoot_start' shooting animation. + 'shoot_end' + 'shoot_speed' + 'die_start' death animation + 'die_end' + 'die_speed' + 'die_loop' when set to false stops the animation looping. + + Using '_loop = false' setting will stop any of the above animations from + looping. + + 'speed_normal' is used for animation speed for compatibility with some + older mobs. + + Note: Up to 5 different animations can be used per action e.g. + stand_start, stand_end, stand1_start, stand1_end .. up to stand4_start + + +Node Replacement +---------------- + +Mobs can look around for specific nodes as they walk and replace them to mimic +eating. + + 'replace_what' group of items to replace e.g. + {"farming:wheat_8", "farming:carrot_8"} + or you can use the specific options of what, with and + y offset by using this instead: + { + {"group:grass", "air", 0}, + {"default:dirt_with_grass", "default:dirt", -1} + } + 'replace_with' replace with what e.g. "air" or in chickens case "mobs:egg" + 'replace_rate' how random should the replace rate be (typically 10) + 'replace_offset' +/- value to check specific node to replace + + 'on_replace(self, pos, oldnode, newnode)' is called when mob is about to + replace a node. + 'self' ObjectRef of mob + 'pos' Position of node to replace + 'oldnode' Current node + 'newnode' What the node will become after replacing + + If false is returned, the mob will not replace the node. + + By default, replacing sets self.gotten to true and resets the object + properties. + + +Custom Definition Functions +--------------------------- + +Along with the above mob registry settings we can also use custom functions to +enhance mob functionality and have them do many interesting things: + + 'on_die' a function that is called when the mob is killed the + parameters are (self, pos) + 'on_rightclick' its same as in minetest.register_entity() + 'on_blast' is called when an explosion happens near mob when using TNT + functions, parameters are (object, damage) and returns + (do_damage, do_knockback, drops) + 'on_spawn' is a custom function that runs on mob spawn with 'self' as + variable, return true at end of function to run only once. + 'after_activate' is a custom function that runs once mob has been activated + with these paramaters (self, staticdata, def, dtime) + 'on_breed' called when two similar mobs breed, paramaters are + (parent1, parent2) objects, return false to stop child from + being resized and owner/tamed flags and child textures being + applied. Function itself must spawn new child mob. + 'on_grown' is called when a child mob has grown up, only paramater is + (self). + 'do_punch' called when mob is punched with paramaters (self, hitter, + time_from_last_punch, tool_capabilities, direction), return + false to stop punch damage and knockback from taking place. + 'custom_attack' when set this function is called instead of the normal mob + melee attack, parameters are (self, to_attack). + 'on_die' a function that is called when mob is killed (self, pos) + 'do_custom' a custom function that is called every tick while mob is + active and which has access to all of the self.* variables + e.g. (self.health for health or self.standing_in for node + status), return with 'false' to skip remainder of mob API. + + +Internal Variables +------------------ + +The mob api also has some preset variables and functions that it will remember +for each mob. + + 'self.health' contains current health of mob (cannot exceed + self.hp_max) + 'self.texture_list' contains list of all mob textures + 'self.child_texture' contains mob child texture when growing up + 'self.base_texture' contains current skin texture which was randomly + selected from textures list + 'self.gotten' this is used for obtaining milk from cow and wool from + sheep + 'self.horny' when animal fed enough it is set to true and animal can + breed with same animal + 'self.hornytimer' background timer that controls breeding functions and + mob childhood timings + 'self.child' used for when breeding animals have child, will use + child_texture and be half size + 'self.owner' string used to set owner of npc mobs, typically used for + dogs + 'self.order' set to "follow" or "stand" so that npc will follow owner + or stand it's ground + 'self.nametag' contains the name of the mob which it can show above + + +Spawning Mobs in World +---------------------- + +mobs:register_spawn(name, nodes, max_light, min_light, chance, + active_object_count, max_height, day_toggle) + +mobs:spawn_specfic(name, nodes, neighbors, min_light, max_light, interval, + chance, active_object_count, min_height, max_height, day_toggle, on_spawn) + +These functions register a spawn algorithm for the mob. Without this function +the call the mobs won't spawn. + + 'name' is the name of the animal/monster + 'nodes' is a list of nodenames on that the animal/monster can + spawn on top of + 'neighbors' is a list of nodenames on that the animal/monster will + spawn beside (default is {"air"} for + mobs:register_spawn) + 'max_light' is the maximum of light + 'min_light' is the minimum of light + 'interval' is same as in register_abm() (default is 30 for + mobs:register_spawn) + 'chance' is same as in register_abm() + 'active_object_count' number of this type of mob to spawn at one time inside + map area + 'min_height' is the minimum height the mob can spawn + 'max_height' is the maximum height the mob can spawn + 'day_toggle' true for day spawning, false for night or nil for + anytime + 'on_spawn' is a custom function which runs after mob has spawned + and gives self and pos values. + +A simpler way to handle mob spawns has been added with the mobs:spawn(def) +command which uses above names to make settings clearer: + + mobs:spawn({name = "mobs_monster:tree_monster", + nodes = {"group:leaves"}, + max_light = 7, + }) + + +For each mob that spawns with this function is a field in mobs.spawning_mobs. +It tells if the mob should spawn or not. Default is true. So other mods can +only use the API of this mod by disabling the spawning of the default mobs in +this mod. + + +mobs:spawn_abm_check(pos, node, name) + +This global function can be changed to contain additional checks for mobs to +spawn e.g. mobs that spawn only in specific areas and the like. By returning +true the mob will not spawn. + + 'pos' holds the position of the spawning mob + 'node' contains the node the mob is spawning on top of + 'name' is the name of the animal/monster + + +Making Arrows +------------- + +mobs:register_arrow(name, definition) + +This function registers a arrow for mobs with the attack type shoot. + + 'name' is the name of the arrow + 'definition' is a table with the following values: + 'visual' same is in minetest.register_entity() + 'visual_size' same is in minetest.register_entity() + 'textures' same is in minetest.register_entity() + 'velocity' the velocity of the arrow + 'drop' if set to true any arrows hitting a node will drop as item + 'hit_player' a function that is called when the arrow hits a player; + this function should hurt the player, the parameters are + (self, player) + 'hit_mob' a function that is called when the arrow hits a mob; + this function should hurt the mob, the parameters are + (self, player) + 'hit_node' a function that is called when the arrow hits a node, the + parameters are (self, pos, node) + 'tail' when set to 1 adds a trail or tail to mob arrows + 'tail_texture' texture string used for above effect + 'tail_size' has size for above texture (defaults to between 5 and 10) + 'expire' contains float value for how long tail appears for + (defaults to 0.25) + 'glow' has value for how brightly tail glows 1 to 10 (default is + 0 for no glow) + 'rotate' integer value in degrees to rotate arrow + 'on_step' is a custom function when arrow is active, nil for + default. + 'on_punch' is a custom function when arrow is punched, nil by default + 'collisionbox' is hitbox table for arrow, {0,0,0,0,0,0} by default. + + +Spawn Eggs +---------- + +mobs:register_egg(name, description, background, addegg, no_creative) + +This function registers a spawn egg which can be used by admin to properly spawn in a mob. + + 'name' this is the name of your new mob to spawn e.g. "mob:sheep" + 'description' the name of the new egg you are creating e.g. "Spawn Sheep" + 'background' the texture displayed for the egg in inventory + 'addegg' would you like an egg image in front of your texture (1 = yes, + 0 = no) + 'no_creative' when set to true this stops spawn egg appearing in creative + mode for destructive mobs like Dungeon Masters. + + +Explosion Function +------------------ + +mobs:explosion(pos, radius) -- DEPRECATED!!! use mobs:boom() instead + +mobs:boom(self, pos, radius) + 'self' mob entity + 'pos' centre position of explosion + 'radius' radius of explosion (typically set to 3) + +This function generates an explosion which removes nodes in a specific radius +and damages any entity caught inside the blast radius. Protection will limit +node destruction but not entity damage. + + +Capturing Mobs +-------------- + +mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, + force_take, replacewith) + +This function is generally called inside the on_rightclick section of the mob +api code, it provides a chance of capturing the mob by hand, using the net or +lasso items, and can also have the player take the mob by force if tamed and +replace with another item entirely. + + 'self' mob information + 'clicker' player information + 'chance_hand' chance of capturing mob by hand (1 to 100) 0 to disable + 'chance_net' chance of capturing mob using net (1 to 100) 0 to disable + 'chance_lasso' chance of capturing mob using magic lasso (1 to 100) 0 to + disable + 'force_take' take mob by force, even if tamed (true or false) + 'replacewith' once captured replace mob with this item instead (overrides + new mob eggs with saved information) + + +Feeding and Taming/Breeding +--------------------------- + +mobs:feed_tame(self, clicker, feed_count, breed, tame) + +This function allows the mob to be fed the item inside self.follow be it apple, +wheat or whatever a set number of times and be tamed or bred as a result. +Will return true when mob is fed with item it likes. + + 'self' mob information + 'clicker' player information + 'feed_count' number of times mob must be fed to tame or breed + 'breed' true or false stating if mob can be bred and a child created + afterwards + 'tame' true or false stating if mob can be tamed so player can pick + them up + + +Protecting Mobs +--------------- + +mobs:protect(self, clicker) + +This function can be used to right-click any tamed mob with mobs:protector item, +this will protect the mob from harm inside of a protected area from other +players. Will return true when mob right-clicked with mobs:protector item. + + 'self' mob information + 'clicker' player information + + +Riding Mobs +----------- + +Mobs can now be ridden by players and the following shows its functions and +usage: + + +mobs:attach(self, player) + +This function attaches a player to the mob so it can be ridden. + + 'self' mob information + 'player' player information + + +mobs:detach(player, offset) + +This function will detach the player currently riding a mob to an offset +position. + + 'player' player information + 'offset' position table containing offset values + + +mobs:drive(self, move_animation, stand_animation, can_fly, dtime) + +This function allows an attached player to move the mob around and animate it at +same time. + + 'self' mob information + 'move_animation' string containing movement animation e.g. "walk" + 'stand_animation' string containing standing animation e.g. "stand" + 'can_fly' if true then jump and sneak controls will allow mob to fly + up and down + 'dtime' tick time used inside drive function + + +mobs:fly(self, dtime, speed, can_shoot, arrow_entity, move_animation, stand_animation) + +This function allows an attached player to fly the mob around using directional +controls. + + 'self' mob information + 'dtime' tick time used inside fly function + 'speed' speed of flight + 'can_shoot' true if mob can fire arrow (sneak and left mouse button + fires) + 'arrow_entity' name of arrow entity used for firing + 'move_animation' string containing name of pre-defined animation e.g. "walk" + or "fly" etc. + 'stand_animation' string containing name of pre-defined animation e.g. + "stand" or "blink" etc. + +Note: animation names above are from the pre-defined animation lists inside mob +registry without extensions. + + +mobs:set_animation(self, name) + +This function sets the current animation for mob, defaulting to "stand" if not +found. + + 'self' mob information + 'name' name of animation + + +Certain variables need to be set before using the above functions: + + 'self.v2' toggle switch used to define below values for the + first time + 'self.max_speed_forward' max speed mob can move forward + 'self.max_speed_reverse' max speed mob can move backwards + 'self.accel' acceleration speed + 'self.terrain_type' integer containing terrain mob can walk on + (1 = water, 2 or 3 = land) + 'self.driver_attach_at' position offset for attaching player to mob + 'self.driver_eye_offset' position offset for attached player view + 'self.driver_scale' sets driver scale for mobs larger than {x=1, y=1} + + +mobs:line_of_sight(self, pos1, pos2, stepsize) + +This function is for use within the mobs definition for special use cases and +returns true if a mob can see the player or victim. + +...'self' mob information + 'pos1' position of mob + 'pos2' position of vistim or player + 'stepsize' usually set to 1 + + +External Settings for "minetest.conf" +------------------------------------ + + 'enable_damage' if true monsters will attack players (default is true) + 'only_peaceful_mobs' if true only animals will spawn in game (default is + false) + 'mobs_disable_blood' if false blood effects appear when mob is hit (default + is false) + 'mobs_spawn_protected' if set to false then mobs will not spawn in protected + areas (default is true) + 'remove_far_mobs' if true then untamed mobs that are outside players + visual range will be removed (default is true) + 'mobname' can change specific mob chance rate (0 to disable) and + spawn number e.g. mobs_animal:cow = 1000,5 + 'mob_difficulty' sets difficulty level (health and hit damage + multiplied by this number), defaults to 1.0. + 'mob_show_health' if false then punching mob will not show health status + (true by default) + 'mob_chance_multiplier' multiplies chance of all mobs spawning and can be set + to 0.5 to have mobs spawn more or 2.0 to spawn less. + e.g. 1 in 7000 * 0.5 = 1 in 3500 so better odds of + spawning. + 'mobs_spawn' if false then mobs no longer spawn without spawner or + spawn egg. + 'mobs_drop_items' when false mobs no longer drop items when they die. + 'mobs_griefing' when false mobs cannot break blocks when using either + pathfinding level 2, replace functions or mobs:boom + function. + +Players can override the spawn chance for each mob registered by adding a line +to their minetest.conf file with a new value, the lower the value the more each +mob will spawn e.g. + +mobs_animal:sheep_chance 11000 +mobs_monster:sand_monster_chance 100 + + +Rideable Horse Example Mob +-------------------------- + +mobs:register_mob("mob_horse:horse", { + type = "animal", + visual = "mesh", + visual_size = {x = 1.20, y = 1.20}, + mesh = "mobs_horse.x", + collisionbox = {-0.4, -0.01, -0.4, 0.4, 1.25, 0.4}, + animation = { + speed_normal = 15, + speed_run = 30, + stand_start = 25, + stand_end = 75, + walk_start = 75, + walk_end = 100, + run_start = 75, + run_end = 100, + }, + textures = { + {"mobs_horse.png"}, + {"mobs_horsepeg.png"}, + {"mobs_horseara.png"} + }, + fear_height = 3, + runaway = true, + fly = false, + walk_chance = 60, + view_range = 5, + follow = {"farming:wheat"}, + passive = true, + hp_min = 12, + hp_max = 16, + armor = 200, + lava_damage = 5, + fall_damage = 5, + water_damage = 1, + makes_footstep_sound = true, + drops = { + {name = "mobs:meat_raw", chance = 1, min = 2, max = 3} + }, + sounds = { + random = "horse_neigh.ogg", + damage = "horse_whinney.ogg", + }, + + do_custom = function(self, dtime) + + -- set needed values if not already present + if not self.v2 then + self.v2 = 0 + self.max_speed_forward = 6 + self.max_speed_reverse = 2 + self.accel = 6 + self.terrain_type = 3 + self.driver_attach_at = {x = 0, y = 20, z = -2} + self.driver_eye_offset = {x = 0, y = 3, z = 0} + self.driver_scale = {x = 1, y = 1} + end + + -- if driver present allow control of horse + if self.driver then + + mobs.drive(self, "walk", "stand", false, dtime) + + return false -- skip rest of mob functions + end + + return true + end, + + on_die = function(self, pos) + + -- drop saddle when horse is killed while riding + -- also detach from horse properly + if self.driver then + minetest.add_item(pos, "mobs:saddle") + mobs.detach(self.driver, {x = 1, y = 0, z = 1}) + end + + end, + + on_rightclick = function(self, clicker) + + -- make sure player is clicking + if not clicker or not clicker:is_player() then + return + end + + -- feed, tame or heal horse + if mobs:feed_tame(self, clicker, 10, true, true) then + return + end + + -- make sure tamed horse is being clicked by owner only + if self.tamed and self.owner == clicker:get_player_name() then + + local inv = clicker:get_inventory() + + -- detatch player already riding horse + if self.driver and clicker == self.driver then + + mobs.detach(clicker, {x = 1, y = 0, z = 1}) + + -- add saddle back to inventory + if inv:room_for_item("main", "mobs:saddle") then + inv:add_item("main", "mobs:saddle") + else + minetest.add_item(clicker.getpos(), "mobs:saddle") + end + + -- attach player to horse + elseif not self.driver + and clicker:get_wielded_item():get_name() == "mobs:saddle" then + + self.object:set_properties({stepheight = 1.1}) + mobs.attach(self, clicker) + + -- take saddle from inventory + inv:remove_item("main", "mobs:saddle") + end + end + + -- used to capture horse with magic lasso + mobs:capture_mob(self, clicker, 0, 0, 80, false, nil) + end +}) diff --git a/mods/mobs/bunny.lua b/mods/mobs/bunny.lua new file mode 100644 index 0000000..d2009ff --- /dev/null +++ b/mods/mobs/bunny.lua @@ -0,0 +1,93 @@ +local S = mobs.intllib +-- Bunny by ExeterDad +mobs:register_mob("mobs:bunny", { + --stepheight = 0.6, + type = "animal", + passive = true, + reach = 1, + hp_min = 6, + hp_max = 6, + armor = 100, + collisionbox = {-0.268, -0.5, -0.268, 0.268, 0.167, 0.268}, + visual = "mesh", + mesh = "mobs_bunny.b3d", + drawtype = "front", + textures = { + {"mobs_bunny_grey.png"}, + {"mobs_bunny_brown.png"}, + --{"mobs_bunny_white.png"}, + }, + --sounds = {}, + makes_footstep_sound = false, + walk_velocity = 1, + run_velocity = 2, + runaway = true, + --runaway_from = {"player"}, + --jump = true, + --jump_height = 6, + drops = { + {name = "mobs:meat_raw", chance = 1, min = 1, max = 2}, + {name = "mobs:leather", chance = 1, min = 0, max = 1}, + }, + water_damage = 1, + lava_damage = 4, + light_damage = 0, + fear_height = 2, + animation = { + speed_normal = 15, + stand_start = 1, + stand_end = 15, + walk_start = 16, + walk_end = 24, + punch_start = 16, + punch_end = 24, + }, + follow = {"default:grass_1", "default:grass_2", "default:grass_3", "default:grass_4", "default:grass_5",}, + --view_range = 8, + --replace_rate = 10, + --replace_what = {"farming:carrot_7", "farming:carrot_8", "farming_plus:carrot"}, + --replace_with = "air", + --[[ + on_spawn = function(self) + local pos = self.object:get_pos() ; pos.y = pos.y - 1 + -- white snowy bunny + if minetest.find_node_near(pos, 1, + {"default:snow", "default:snowblock", "default:dirt_with_snow"}) then + self.base_texture = {"mobs_bunny_white.png"} + self.object:set_properties({textures = self.base_texture}) + -- brown desert bunny + elseif minetest.find_node_near(pos, 1, + {"default:desert_sand", "default:desert_stone"}) then + self.base_texture = {"mobs_bunny_brown.png"} + self.object:set_properties({textures = self.base_texture}) + -- grey stone bunny + elseif minetest.find_node_near(pos, 1, + {"default:stone", "default:gravel"}) then + self.base_texture = {"mobs_bunny_grey.png"} + self.object:set_properties({textures = self.base_texture}) + end + return true -- run only once, false/nil runs every activation + end, + --]] + on_rightclick = function(self, clicker) + if mobs:feed_tame(self, clicker, 4, true, true) then return end + if mobs:protect(self, clicker) then return end + if mobs:capture_mob(self, clicker, 50, 50, 90, false, nil) then return end + + -- by right-clicking owner can switch between staying and walking + if self.owner and self.owner == clicker:get_player_name() then + if self.order ~= "stand" then + self.order = "stand" + self.state = "stand" + self.object:set_velocity({x = 0, y = 0, z = 0}) + mobs:set_animation(self, "stand") + else + self.order = "" + mobs:set_animation(self, "stoodup") + end + end + end, + attack_type = "dogfight", + damage = 5, +}) +mobs:register_egg("mobs:bunny", S("Bunny"), "mobs_bunny_inv.png", 0) diff --git a/mods/mobs/crafts.lua b/mods/mobs/crafts.lua new file mode 100644 index 0000000..1d68731 --- /dev/null +++ b/mods/mobs/crafts.lua @@ -0,0 +1,113 @@ +local S = mobs.intllib + +minetest.register_craftitem("mobs:rotten_flesh", { + description = "Rotten Flesh", + inventory_image = "mobs_rotten_flesh.png", + on_use = minetest.item_eat(-2), +}) +minetest.register_craft({ + type = "cooking", + output = "mobs:meat", + recipe = "mobs:rotten_flesh", + cooktime = 12, +}) + +local hairball_items = { + "default:stick", "default:coal_lump", "default:dry_shrub", "flowers:rose", + "mobs:rat", "default:grass_1", "farming:seed_wheat", "dye:green", + "farming:seed_cotton", "default:flint", "default:sapling", "dye:white", + "default:clay_lump", "default:paper", "default:dry_grass_1", "dye:red", + "farming:string", "default:acacia_bush_sapling", + "default:bush_sapling", "default:copper_lump", "default:iron_lump", + "dye:black", "dye:brown", "default:obsidian_shard", "default:tin_lump" +} +minetest.register_craftitem("mobs:hairball", { + description = S("Lucky Hairball"), + inventory_image = "farming_string.png^(farming_string.png^[transformFYR90)", + on_use = function(itemstack, user, pointed_thing) + local pos = user:get_pos() + local dir = user:get_look_dir() + local newpos = {x = pos.x + dir.x, y = pos.y + dir.y + 1.5, z = pos.z + dir.z} + local item = hairball_items[math.random(1, #hairball_items)] + if item ~= "" then + minetest.add_item(newpos, {name = item}) + end + minetest.sound_play("default_place_node_hard", { + pos = newpos, + gain = 0.8, + }) + itemstack:take_item() + return itemstack + end, +}) + +-- name tag +minetest.register_craftitem("mobs:nametag", { + description = S("Name Tag"), + inventory_image = "mobs_nametag.png", + groups = {flammable = 2}, +}) + +minetest.register_craft({ + type = "shapeless", + output = "mobs:nametag", + recipe = {"default:paper", "dye:black", "farming:string"}, +}) + +-- leather +minetest.register_craftitem("mobs:leather", { + description = S("Leather"), + inventory_image = "mobs_leather.png", + groups = {flammable = 2}, + on_use = minetest.item_eat(1), +}) + +-- raw meat +minetest.register_craftitem("mobs:meat_raw", { + description = S("Raw Meat"), + inventory_image = "mobs_meat_raw.png", + on_use = minetest.item_eat(3), + groups = {food_meat_raw = 1, flammable = 2}, +}) + +-- cooked meat +minetest.register_craftitem("mobs:meat", { + description = S("Meat"), + inventory_image = "mobs_meat.png", + on_use = minetest.item_eat(8), + groups = {food_meat = 1, flammable = 2}, +}) + +minetest.register_craft({ + type = "cooking", + output = "mobs:meat", + recipe = "mobs:meat_raw", + cooktime = 5, +}) + +-- shears (right click to shear animal) +minetest.register_tool("mobs:shears", { + description = S("Steel Shears"), + inventory_image = "mobs_shears.png", + groups = {flammable = 2}, +}) +minetest.register_craft({ + output = "mobs:shears", + recipe = { + {"", "default:steel_ingot", ""}, + {"", "group:stick", "default:steel_ingot"}, + } +}) + +-- items that can be used as fuel +minetest.register_craft({ + type = "fuel", + recipe = "mobs:nametag", + burntime = 3, +}) + +minetest.register_craft({ + type = "fuel", + recipe = "mobs:leather", + burntime = 4, +}) diff --git a/mods/mobs/depends.txt b/mods/mobs/depends.txt new file mode 100644 index 0000000..2f20802 --- /dev/null +++ b/mods/mobs/depends.txt @@ -0,0 +1,9 @@ +default +tnt? +dye? +farming? +invisibility? +intllib? +lucky_block? +cmi? +toolranks? diff --git a/mods/mobs/description.txt b/mods/mobs/description.txt new file mode 100644 index 0000000..919852a --- /dev/null +++ b/mods/mobs/description.txt @@ -0,0 +1 @@ +Adds a mob api for mods to add animals or monsters etc. \ No newline at end of file diff --git a/mods/mobs/dungeon_master.lua b/mods/mobs/dungeon_master.lua new file mode 100644 index 0000000..9bdd442 --- /dev/null +++ b/mods/mobs/dungeon_master.lua @@ -0,0 +1,112 @@ +local S = mobs.intllib +-- Dungeon Master by PilzAdam +mobs:register_mob("mobs:dungeon_master", { + type = "monster", + passive = false, + damage = 6, + attack_type = "dogshoot", + dogshoot_switch = 1, + dogshoot_count_max = 12, -- shoot for 10 seconds + dogshoot_count2_max = 3, -- dogfight for 3 seconds + reach = 2, + shoot_interval = 2.2, + arrow = "mobs:fireball", + shoot_offset = 1, + hp_min = 20, + hp_max = 20, + armor = 100, + collisionbox = {-0.7, -1, -0.7, 0.7, 1.6, 0.7}, + visual = "mesh", + mesh = "mobs_dungeon_master.b3d", + textures = { + {"mobs_dungeon_master.png"}, + {"mobs_dungeon_master2.png"}, + {"mobs_dungeon_master3.png"}, + }, + makes_footstep_sound = true, + sounds = { + random = "mobs_dungeonmaster", + shoot_attack = "mobs_fireball", + }, + walk_velocity = 1, + --run_velocity = 1, + --jump = true, + --view_range = 15, + drops = { + {name = "default:mese_crystal", chance = 1, min = 1, max = 2}, + {name = "default:diamond", chance = 2, min = 0, max = 1}, + }, + water_damage = 1, + lava_damage = 1, + light_damage = 0, + fear_height = 3, + animation = { + stand_start = 0, + stand_end = 19, + walk_start = 20, + walk_end = 35, + punch_start = 36, + punch_end = 48, + shoot_start = 36, + shoot_end = 48, + speed_normal = 15, + speed_run = 15, + }, +}) + +mobs:register_egg("mobs:dungeon_master", S("Dungeon Master"), "fire_basic_flame.png", 1, true) + +-- fireball (weapon) +mobs:register_arrow("mobs:fireball", { + visual = "sprite", + visual_size = {x = 1, y = 1}, + textures = {"mobs_fireball.png"}, + collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1}, + velocity = 7, + --tail = 1, + --tail_texture = "mobs_fireball.png", + --tail_size = 10, + glow = 14, + expire = 0.1, + on_activate = function(self, staticdata, dtime_s) + -- make fireball indestructable + self.object:set_armor_groups({immortal = 1, fleshy = 100}) + end, + -- if player has a good weapon with 7+ damage it can deflect fireball + on_punch = function(self, hitter, tflp, tool_capabilities, dir) + if hitter and hitter:is_player() and + tool_capabilities and dir then + local damage = tool_capabilities.damage_groups and + tool_capabilities.damage_groups.fleshy or 1 + local tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + if damage > 6 and tmp < 4 then + self.object:set_velocity({ + x = dir.x * self.velocity, + y = dir.y * self.velocity, + z = dir.z * self.velocity, + }) + end + end + end, + -- direct hit, no fire... just plenty of pain + hit_player = function(self, player) + player:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, nil) + tnt.boom(self.object:get_pos(), {radius = 3}) + end, + + hit_mob = function(self, player) + player:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, nil) + tnt.boom(self.object:get_pos(), {radius = 3}) + end, + + -- node hit + hit_node = function(self, pos, node) + tnt.boom(self.object:get_pos(), {radius = 3}) + end +}) diff --git a/mods/mobs/init.lua b/mods/mobs/init.lua new file mode 100644 index 0000000..feaa723 --- /dev/null +++ b/mods/mobs/init.lua @@ -0,0 +1,59 @@ +local path = minetest.get_modpath(minetest.get_current_modname()) +local stepper = 0 +minetest.register_globalstep(function(dtime) + if stepper < 12 then + stepper = stepper + dtime + return + else + stepper = 0 + end + local players = minetest.get_connected_players() + for i = 1, #players do + if players[i] == "" then + break + end + local pos = players[i]:get_pos() + if not pos then + break + end + local t = 0 + for k, v in pairs(minetest.get_objects_inside_radius(pos, 16)) do + local s = v:get_luaentity() + if s and s.health then + t = t + 1 + end + if t >= 6 then + return v:remove() + end + end + if minetest.find_node_near(pos, 8, "mobs:spawner") then + break + end + if not minetest.get_node_or_nil(pos) then + break + end + if minetest.get_node_or_nil(pos).name ~= "air" then + pos.y = pos.y + 1 + end + if minetest.get_node_or_nil(pos).name ~= "air" then + break + end + local added = minetest.add_node(pos, {name = "mobs:spawner"}) + if not added then + break + end + minetest.get_node_timer(pos):start(0) + end +end) + +dofile(path .. "/api.lua") +dofile(path .. "/crafts.lua") +dofile(path .. "/nodes.lua") +dofile(path .. "/npc.lua") +dofile(path .. "/sheep.lua") +dofile(path .. "/rat.lua") +dofile(path .. "/bunny.lua") +dofile(path .. "/kitten.lua") +dofile(path .. "/dungeon_master.lua") +dofile(path .. "/oerkki.lua") +dofile(path .. "/zombies.lua") diff --git a/mods/mobs/intllib.lua b/mods/mobs/intllib.lua new file mode 100644 index 0000000..6669d72 --- /dev/null +++ b/mods/mobs/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/mods/mobs/kitten.lua b/mods/mobs/kitten.lua new file mode 100644 index 0000000..7a5cd14 --- /dev/null +++ b/mods/mobs/kitten.lua @@ -0,0 +1,95 @@ +local S = mobs.intllib +local hairball = minetest.settings:get("mobs_hairball") + +-- Kitten by Jordach / BFD +mobs:register_mob("mobs:kitten", { + --stepheight = 0.6, + type = "animal", + specific_attack = {"mobs:rat"}, + damage = 1, + attack_type = "dogfight", + attack_animals = true, -- so it can attack rat + attack_players = false, + reach = 1, + passive = false, + hp_min = 5, + hp_max = 10, + armor = 200, + collisionbox = {-0.3, -0.3, -0.3, 0.3, 0.1, 0.3}, + visual = "mesh", + visual_size = {x = 0.5, y = 0.5}, + mesh = "mobs_kitten.b3d", + textures = { + {"mobs_kitten_striped.png"}, + {"mobs_kitten_splotchy.png"}, + {"mobs_kitten_ginger.png"}, + --{"mobs_kitten_sandy.png"}, + }, + makes_footstep_sound = false, + sounds = { + random = "mobs_kitten", + }, + walk_velocity = 0.6, + walk_chance = 15, + run_velocity = 2, + runaway = true, + --jump = false, + drops = { + {name = "mobs:meat_raw", chance = 1, min = 1, max = 2}, + {name = "mobs:hairball", chance = 2, min = 0, max = 1}, + }, + water_damage = 1, + lava_damage = 5, + fear_height = 3, + animation = { + speed_normal = 42, + stand_start = 97, + stand_end = 192, + walk_start = 0, + walk_end = 96, + stoodup_start = 0, + stoodup_end = 0, + }, + follow = {"mobs:rat"}, + --view_range = 8, + on_rightclick = function(self, clicker) + if mobs:feed_tame(self, clicker, 4, true, true) then return end + if mobs:protect(self, clicker) then return end + if mobs:capture_mob(self, clicker, 50, 50, 90, false, nil) then return end + + -- by right-clicking owner can switch between staying and walking + if self.owner and self.owner == clicker:get_player_name() then + if self.order ~= "stand" then + self.order = "stand" + self.state = "stand" + self.object:set_velocity({x = 0, y = 0, z = 0}) + mobs:set_animation(self, "stand") + else + self.order = "" + mobs:set_animation(self, "stoodup") + end + end + end, + do_custom = function(self, dtime) + if hairball == "false" then + return + end + self.hairball_timer = (self.hairball_timer or 0) + dtime + if self.hairball_timer < 10 then + return + end + self.hairball_timer = 0 + if self.child + or math.random(1, 250) > 1 then + return + end + local pos = self.object:get_pos() + minetest.add_item(pos, "mobs:hairball") + minetest.sound_play("mobs_kitten", { + pos = pos, + gain = 0.5, + max_hear_distance = 128, + }) + end, +}) +mobs:register_egg("mobs:kitten", S("Kitten"), "mobs_kitten_ginger.png", 1) diff --git a/mods/mobs/license.txt b/mods/mobs/license.txt new file mode 100644 index 0000000..fec6f6a --- /dev/null +++ b/mods/mobs/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TenPlus1 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/mods/mobs/locale/de_DE.po b/mods/mobs/locale/de_DE.po new file mode 100644 index 0000000..210990d --- /dev/null +++ b/mods/mobs/locale/de_DE.po @@ -0,0 +1,131 @@ +# Mobs Redo translation. +# Copyright (C) 2017 TenPlus1 +# This file is distributed under the same license as the mobs package. +# Wuzzy , 2017 +# +msgid "" +msgstr "" +"Project-Id-Version: mobs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 16:48+0200\n" +"PO-Revision-Date: 2017-07-02 14:27+0200\n" +"Last-Translator: Wuzzy \n" +"Language-Team: \n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "Kreatur wurde geschützt!" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (Gezähmt)" + +#: api.lua +msgid "Not tamed!" +msgstr "Nicht gezähmt!" + +#: api.lua +msgid "@1 is owner!" +msgstr "@1 ist der Besitzer!" + +#: api.lua +msgid "Missed!" +msgstr "Daneben!" + +#: api.lua +msgid "Already protected!" +msgstr "Bereits geschützt!" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 bei voller Gesundheit (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 wurde gezähmt!" + +#: api.lua +msgid "Enter name:" +msgstr "Namen eingeben:" + +#: api.lua +msgid "Rename" +msgstr "Umbenennen" + +#: crafts.lua +msgid "Name Tag" +msgstr "Namensschild" + +#: crafts.lua +msgid "Leather" +msgstr "Leder" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Rohes Fleisch" + +#: crafts.lua +msgid "Meat" +msgstr "Fleisch" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Lasso (Rechtsklick auf Tier, um es zu nehmen)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Netz (Rechtsklick auf Tier, um es zu nehmen)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Stahlschere (Rechtsklick zum Scheren)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Kreaturschutzrune" + +#: crafts.lua +msgid "Saddle" +msgstr "Sattel" + +#: crafts.lua +msgid "Mob Fence" +msgstr "Kreaturen Zaun" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Kreaturenspawner" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Kreatur MinLicht MaxLicht Menge SpielerEntfng" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Nicht aktiv (Einstellungen eingeben)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Spawner aktiv (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Kreaturenspawner-Einstellungen gescheitert!" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" +"Syntax: „name min_licht[0-14] max_licht[0-14] max_mobs_im_gebiet[0 zum " +"Deaktivieren] distanz[1-20] y_versatz[-10 bis 10]“" diff --git a/mods/mobs/locale/es.po b/mods/mobs/locale/es.po new file mode 100644 index 0000000..849db66 --- /dev/null +++ b/mods/mobs/locale/es.po @@ -0,0 +1,128 @@ +# Mobs Redo translation. +# Copyright (C) 2017 TenPlus1 +# This file is distributed under the same license as the mobs package. +# Wuzzy , 2017 +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-16 16:48+0200\n" +"PO-Revision-Date: 2017-07-16 16:48+0200\n" +"Last-Translator: Aleks \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "El mob ha sido protegido!" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (Domesticado)" + +#: api.lua +msgid "Not tamed!" +msgstr "No domesticado!" + +#: api.lua +msgid "@1 is owner!" +msgstr "@1 es el dueño!" + +#: api.lua +msgid "Missed!" +msgstr "Perdido!" + +#: api.lua +msgid "Already protected!" +msgstr "Ya está protegido!" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 con salud llena (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 ha sido domesticado!" + +#: api.lua +msgid "Enter name:" +msgstr "Ingrese nombre:" + +#: api.lua +msgid "Rename" +msgstr "Renombrar" + +#: crafts.lua +msgid "Name Tag" +msgstr "Nombrar etiqueta" + +#: crafts.lua +msgid "Leather" +msgstr "Cuero" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Carne cruda" + +#: crafts.lua +msgid "Meat" +msgstr "Carne" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Lazo (click derecho en animal para colocar en inventario)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Red (click derecho en animal para colocar en inventario)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Tijera de acero (click derecho para esquilar)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Runa de protección de Mob" + +#: crafts.lua +msgid "Saddle" +msgstr "Montura" + +#: crafts.lua +msgid "Mob Fence" +msgstr "" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Generador de Mob" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob LuzMin LuzMax Cantidad DistJugador" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Generador no activo (ingrese config)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Generador activo (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Configuracion de generador de Mob falló!" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "Sintaxis: “nombre luz_min[0-14] luz_max[0-14] max_mobs_en_area[0 para deshabilitar] " +"distancia[1-20] compensacion[-10 a 10]”" diff --git a/mods/mobs/locale/fr.po b/mods/mobs/locale/fr.po new file mode 100644 index 0000000..25b920c --- /dev/null +++ b/mods/mobs/locale/fr.po @@ -0,0 +1,129 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-29 09:13+0200\n" +"PO-Revision-Date: 2017-07-29 09:20+0200\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.12\n" +"Last-Translator: fat115 \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Language: fr\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "** Mode pacifique activé - Aucun monstre ne sera généré" + +#: api.lua +msgid "Mob has been protected!" +msgstr "L'animal a été protégé !" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (apprivoisé)" + +#: api.lua +msgid "Not tamed!" +msgstr "Non-apprivoisé !" + +#: api.lua +msgid "@1 is owner!" +msgstr "Appartient à @1 !" + +#: api.lua +msgid "Missed!" +msgstr "Raté !" + +#: api.lua +msgid "Already protected!" +msgstr "Déjà protégé !" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 est en pleine forme (@2) " + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 a été apprivoisé ! " + +#: api.lua +msgid "Enter name:" +msgstr "Saisissez un nom :" + +#: api.lua +msgid "Rename" +msgstr "Renommer" + +#: crafts.lua +msgid "Name Tag" +msgstr "Étiquette pour collier" + +#: crafts.lua +msgid "Leather" +msgstr "Cuir" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Viande crue" + +#: crafts.lua +msgid "Meat" +msgstr "Viande" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Lasso (clic droit sur l'animal pour le mettre dans l'inventaire)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Filet (clic droit sur l'animal pour le mettre dans l'inventaire)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Ciseaux à laine (clic droit pour tondre)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Rune de protection des animaux" + +#: crafts.lua +msgid "Saddle" +msgstr "Selle" + +#: crafts.lua +msgid "Mob Fence" +msgstr "Clôture à animaux" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Générateur de mob" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob MinLumière MaxLumière Quantité DistanceJoueur" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Générateur non actif (entrez les paramètres)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Générateur actif (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Echec des paramètres du générateur" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "Syntaxe : “nom min_lumière[0-14] max_lumière[0-14] max_mobs_dans_zone[0 pour désactiver] distance[1-20] décalage_y[-10 à 10]“" diff --git a/mods/mobs/locale/it.po b/mods/mobs/locale/it.po new file mode 100644 index 0000000..a439f6d --- /dev/null +++ b/mods/mobs/locale/it.po @@ -0,0 +1,131 @@ +# ITALIAN LOCALE FILE FOR THE MOBS REDO MODULE +# Copyright (c) 2014 Krupnov Pavel and 2016 TenPlus1 +# This file is distributed under the same license as the MOBS REDO package. +# Hamlet , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: Italian locale file for the Mobs Redo module\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 16:48+0200\n" +"PO-Revision-Date: 2017-08-18 12:18+0100\n" +"Last-Translator: H4mlet \n" +"Language-Team: \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.6.10\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "Il mob è stato protetto!" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (Addomesticat*)" + +#: api.lua +msgid "Not tamed!" +msgstr "Non addomesticat*!" + +#: api.lua +msgid "@1 is owner!" +msgstr "Proprietari* @1!" + +#: api.lua +msgid "Missed!" +msgstr "Mancat*!" + +#: api.lua +msgid "Already protected!" +msgstr "Già protett*!" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 in piena salute (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 è stat* addomesticat*!" + +#: api.lua +msgid "Enter name:" +msgstr "Inserire il nome:" + +#: api.lua +msgid "Rename" +msgstr "Rinominare" + +#: crafts.lua +msgid "Name Tag" +msgstr "Targhetta" + +#: crafts.lua +msgid "Leather" +msgstr "Pelle" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Carne cruda" + +#: crafts.lua +msgid "Meat" +msgstr "Carne" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Lazo (click di destro per mettere l'animale nell'inventario)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Rete (click destro per mettere l'animale nell'inventario)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Cesoie d'acciaio (click destro per tosare)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Runa di protezione per mob" + +#: crafts.lua +msgid "Saddle" +msgstr "Sella" + +#: crafts.lua +msgid "Mob Fence" +msgstr "" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Generatore di mob" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob LuceMin LuceMax Ammontare DistGiocat." + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Generatore inattivo (inserire le impostazioni)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Generatore attivo (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Impostazioni del generatore di mob fallite!" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" +"Sintassi: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 per " +"disabilitare] distance[1-20] y_offset[-10 to 10]”" diff --git a/mods/mobs/locale/ms.po b/mods/mobs/locale/ms.po new file mode 100644 index 0000000..a2a31f3 --- /dev/null +++ b/mods/mobs/locale/ms.po @@ -0,0 +1,131 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-05 23:40+0800\n" +"PO-Revision-Date: 2018-02-05 23:51+0800\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.6\n" +"Last-Translator: MuhdNurHidayat (MNH48) \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ms\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "** Mod Aman Diaktifkan - Tiada Raksasa Akan Muncul" + +#: api.lua +msgid "Mob has been protected!" +msgstr "Mob telah pun dilindungi!" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (Jinak)" + +#: api.lua +msgid "Not tamed!" +msgstr "Belum dijinakkan!" + +#: api.lua +msgid "@1 is owner!" +msgstr "Ini hak milik @1!" + +#: api.lua +msgid "Missed!" +msgstr "Terlepas!" + +#: api.lua +msgid "Already protected!" +msgstr "Telah dilindungi!" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "Mata kesihatan @1 telah penuh (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 telah dijinakkan!" + +#: api.lua +msgid "Enter name:" +msgstr "Masukkan nama:" + +#: api.lua +msgid "Rename" +msgstr "Namakan semula" + +#: crafts.lua +msgid "Name Tag" +msgstr "Tanda Nama" + +#: crafts.lua +msgid "Leather" +msgstr "Kulit" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Daging Mentah" + +#: crafts.lua +msgid "Meat" +msgstr "Daging Bakar" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Tanjul (klik-kanan haiwan untuk masukkan ke inventori)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Jaring (klik-kanan haiwan untuk masukkan ke inventori)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Ketam Keluli (klik-kanan untuk mengetam bulu biri-biri)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Rune Perlindungan Mob" + +#: crafts.lua +msgid "Saddle" +msgstr "Pelana" + +#: crafts.lua +msgid "Mob Fence" +msgstr "Pagar Mob" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Pewujud Mob" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob CahayaMin CahayaMax Amaun JarakPemain" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Pewujud Mob Tidak Aktif (masukkan tetapan)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Pewujud Mob Aktif (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Penetapan Pewujud Mob gagal!" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" +"Sintaks: \"nama cahaya_minimum[0-14] cahaya_maksimum[0-14] " +"amaun_mob_maksimum[0 untuk lumpuhkan] jarak[1-20] ketinggian[-10 hingga 10]\"" diff --git a/mods/mobs/locale/pt.po b/mods/mobs/locale/pt.po new file mode 100644 index 0000000..b52afd6 --- /dev/null +++ b/mods/mobs/locale/pt.po @@ -0,0 +1,133 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: mobs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 16:48+0200\n" +"PO-Revision-Date: 2017-07-02 14:55+0200\n" +"Last-Translator: Wuzzy \n" +"Language-Team: \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "" + +#: api.lua +msgid "Not tamed!" +msgstr "Indomesticado!" + +#: api.lua +msgid "@1 is owner!" +msgstr "Dono @1!" + +#: api.lua +msgid "Missed!" +msgstr "Faltou!" + +#: api.lua +msgid "Already protected!" +msgstr "" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 em plena saude (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 foi domesticado!" + +#: api.lua +msgid "Enter name:" +msgstr "Insira um nome:" + +#: api.lua +msgid "Rename" +msgstr "Renomear" + +#: crafts.lua +msgid "Name Tag" +msgstr "Etiqueta" + +#: crafts.lua +msgid "Leather" +msgstr "Couro" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Carne crua" + +#: crafts.lua +msgid "Meat" +msgstr "Carne" + +#: crafts.lua +#, fuzzy +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Laço (clique-direito no animal para por no inventario)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Net (clique-direito no animal para por no inventario)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Tesoura de Aço (clique-direito para tosquiar)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "" + +#: crafts.lua +msgid "Saddle" +msgstr "" + +#: crafts.lua +msgid "Mob Fence" +msgstr "" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Spawnador de Mob" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob LuzMinima LuzMaxima Valor DistJogador" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Spawnador Inativo (configurar)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Spawnador Ativo (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Configuraçao de Spawnador do Mob falhou!" + +#: spawner.lua +#, fuzzy +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" +"> nome luz_min[0-14] luz_max[0-14] max_mobs_na_area[0 para desabilitar] " +"distancia[1-20] y_offset[-10 a 10]" diff --git a/mods/mobs/locale/ru.po b/mods/mobs/locale/ru.po new file mode 100644 index 0000000..6cde7ef --- /dev/null +++ b/mods/mobs/locale/ru.po @@ -0,0 +1,129 @@ +# Russian translation for the mobs_redo mod. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the mobs_redo package. +# Oleg720 , 2017. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-08-13 15:47+0200\n" +"PO-Revision-Date: 2018-03-23 22:22+0100\n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "** Мирный модус активирован - монстры не спаунятся" + +#: api.lua +msgid "Mob has been protected!" +msgstr "Моб защищен!" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "@1 (Прирученный)" + +#: api.lua +msgid "Not tamed!" +msgstr "Не прирученный" + +#: api.lua +msgid "@1 is owner!" +msgstr "@1 владелец" + +#: api.lua +msgid "Missed!" +msgstr "Промазал!" + +#: api.lua +msgid "Already protected!" +msgstr "Уже защищен!" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 при полном здоровье (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 приручен" + +#: api.lua +msgid "Enter name:" +msgstr "Введите имя:" + +#: api.lua +msgid "Rename" +msgstr "Переименовать" + +#: crafts.lua +msgid "Name Tag" +msgstr "Новый тэг" + +#: crafts.lua +msgid "Leather" +msgstr "Кожа" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Сырое мясо" + +#: crafts.lua +msgid "Meat" +msgstr "Мясо" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Лассо (Правый клик - положить животное в инвентарь)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Сеть (Правый клик - положить животное в инвентарь)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Ножницы (Правый клик - подстричь)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "Защитная руна мобов" + +#: crafts.lua +msgid "Saddle" +msgstr "Седло" + +#: crafts.lua +msgid "Mob Fence" +msgstr "Забор от мобов" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Спаунер моба" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Спаунер не активен (введите настройки)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Активные спаунер (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Настройки спаунера моба провалились" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" diff --git a/mods/mobs/locale/template.pot b/mods/mobs/locale/template.pot new file mode 100644 index 0000000..af31440 --- /dev/null +++ b/mods/mobs/locale/template.pot @@ -0,0 +1,128 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 16:48+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "" + +#: api.lua +msgid "Not tamed!" +msgstr "" + +#: api.lua +msgid "@1 is owner!" +msgstr "" + +#: api.lua +msgid "Missed!" +msgstr "" + +#: api.lua +msgid "Already protected!" +msgstr "" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "" + +#: api.lua +msgid "Enter name:" +msgstr "" + +#: api.lua +msgid "Rename" +msgstr "" + +#: crafts.lua +msgid "Name Tag" +msgstr "" + +#: crafts.lua +msgid "Leather" +msgstr "" + +#: crafts.lua +msgid "Raw Meat" +msgstr "" + +#: crafts.lua +msgid "Meat" +msgstr "" + +#: crafts.lua +msgid "Lasso (right-click animal to put in inventory)" +msgstr "" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "" + +#: crafts.lua +msgid "Saddle" +msgstr "" + +#: crafts.lua +msgid "Mob Fence" +msgstr "" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "" + +#: spawner.lua +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" diff --git a/mods/mobs/locale/tr.po b/mods/mobs/locale/tr.po new file mode 100644 index 0000000..10688e2 --- /dev/null +++ b/mods/mobs/locale/tr.po @@ -0,0 +1,133 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: mobs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-02 16:48+0200\n" +"PO-Revision-Date: 2017-07-02 14:56+0200\n" +"Last-Translator: Wuzzy \n" +"Language-Team: \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.2\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: api.lua +msgid "** Peaceful Mode Active - No Monsters Will Spawn" +msgstr "" + +#: api.lua +msgid "Mob has been protected!" +msgstr "" + +#: api.lua +msgid "@1 (Tamed)" +msgstr "" + +#: api.lua +msgid "Not tamed!" +msgstr "Evcil değil!" + +#: api.lua +msgid "@1 is owner!" +msgstr "Sahibi @1!" + +#: api.lua +msgid "Missed!" +msgstr "Kaçırdın!" + +#: api.lua +msgid "Already protected!" +msgstr "" + +#: api.lua +msgid "@1 at full health (@2)" +msgstr "@1 tam canında (@2)" + +#: api.lua +msgid "@1 has been tamed!" +msgstr "@1 tamamen evcilleştirilmiştir!" + +#: api.lua +msgid "Enter name:" +msgstr "İsim gir:" + +#: api.lua +msgid "Rename" +msgstr "Yeniden adlandır" + +#: crafts.lua +msgid "Name Tag" +msgstr "İsim etiketi" + +#: crafts.lua +msgid "Leather" +msgstr "Deri" + +#: crafts.lua +msgid "Raw Meat" +msgstr "Çiğ et" + +#: crafts.lua +msgid "Meat" +msgstr "Et" + +#: crafts.lua +#, fuzzy +msgid "Lasso (right-click animal to put in inventory)" +msgstr "Kement (hayvana sağ tıklayarak envantere koy)" + +#: crafts.lua +msgid "Net (right-click animal to put in inventory)" +msgstr "Ağ (hayvana sağ tıklayarak envantere koy)" + +#: crafts.lua +msgid "Steel Shears (right-click to shear)" +msgstr "Çelik makas (sağ tıklayarak kes)" + +#: crafts.lua +msgid "Mob Protection Rune" +msgstr "" + +#: crafts.lua +msgid "Saddle" +msgstr "" + +#: crafts.lua +msgid "Mob Fence" +msgstr "Canavar Yaratıcı" + +#: spawner.lua +msgid "Mob Spawner" +msgstr "Canavar Yaratıcı" + +#: spawner.lua +msgid "Mob MinLight MaxLight Amount PlayerDist" +msgstr "Mob MinIşık MaxIşık Miktar OyuncuMesafesi" + +#: spawner.lua +msgid "Spawner Not Active (enter settings)" +msgstr "Yaratıcı aktif değil (ayarlara gir)" + +#: spawner.lua +msgid "Spawner Active (@1)" +msgstr "Yaratıcı aktif (@1)" + +#: spawner.lua +msgid "Mob Spawner settings failed!" +msgstr "Yaratıcı ayarları uygulanamadı." + +#: spawner.lua +#, fuzzy +msgid "" +"Syntax: “name min_light[0-14] max_light[0-14] max_mobs_in_area[0 to disable] " +"distance[1-20] y_offset[-10 to 10]”" +msgstr "" +"> isim min_isik[0-14] max_isik[0-14] alandaki_max_canavar_sayisi[kapatmak " +"icin 0] mesafe[1-20] y_cikinti[-10 ve 10 arası]" diff --git a/mods/mobs/mod.conf b/mods/mobs/mod.conf new file mode 100644 index 0000000..f3a3ad7 --- /dev/null +++ b/mods/mobs/mod.conf @@ -0,0 +1 @@ +name = mobs diff --git a/mods/mobs/models/Zombie.blend b/mods/mobs/models/Zombie.blend new file mode 100644 index 0000000..e7ea31b Binary files /dev/null and b/mods/mobs/models/Zombie.blend differ diff --git a/mods/mobs/models/Zombie_base.blend b/mods/mobs/models/Zombie_base.blend new file mode 100644 index 0000000..1830d61 Binary files /dev/null and b/mods/mobs/models/Zombie_base.blend differ diff --git a/mods/mobs/models/Zombie_crawler.blend b/mods/mobs/models/Zombie_crawler.blend new file mode 100644 index 0000000..fc6fc82 Binary files /dev/null and b/mods/mobs/models/Zombie_crawler.blend differ diff --git a/mods/mobs/models/Zombie_one-arm.blend b/mods/mobs/models/Zombie_one-arm.blend new file mode 100644 index 0000000..87f186c Binary files /dev/null and b/mods/mobs/models/Zombie_one-arm.blend differ diff --git a/mods/mobs/models/creatures_mob.x b/mods/mobs/models/creatures_mob.x new file mode 100644 index 0000000..186943f --- /dev/null +++ b/mods/mobs/models/creatures_mob.x @@ -0,0 +1,5524 @@ +xof 0303txt 0032 + +template XSkinMeshHeader { + <3cf169ce-ff7c-44ab-93c0-f78f62d172e2> + WORD nMaxSkinWeightsPerVertex; + WORD nMaxSkinWeightsPerFace; + WORD nBones; +} + +template SkinWeights { + <6f0d123b-bad2-4167-a0d0-80224f25fabb> + STRING transformNodeName; + DWORD nWeights; + array DWORD vertexIndices[nWeights]; + array float weights[nWeights]; + Matrix4x4 matrixOffset; +} + +Frame Root { + FrameTransformMatrix { + 1.000000, 0.000000, 0.000000, 0.000000, + 0.000000,-0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 1.000000;; + } + Frame Armature { + FrameTransformMatrix { + 1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 0.000000,-10.000000, 1.000000;; + } + Frame Armature_Body { + FrameTransformMatrix { + 1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000,-1.000000, 0.000000, 0.000000, + -0.000000, 0.000000, 6.750000, 1.000000;; + } + Frame Armature_Arm_Left { + FrameTransformMatrix { + 0.989214,-0.143886,-0.027450, 0.000000, + -0.143940,-0.989586,-0.000000, 0.000000, + -0.027164, 0.003951,-0.999623, 0.000000, + -2.000000, 6.750000, 0.000000, 1.000000;; + } + } // End of Armature_Arm_Left + Frame Armature_Arm_Right { + FrameTransformMatrix { + 0.989214, 0.143886, 0.027450, 0.000000, + 0.143940,-0.989586,-0.000000, 0.000000, + 0.027164, 0.003951,-0.999623, 0.000000, + 2.000000, 6.750000, 0.000000, 1.000000;; + } + } // End of Armature_Arm_Right + Frame Armature_Head { + FrameTransformMatrix { + -1.000000,-0.000000, 0.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -0.000000, 0.000000,-1.000000, 0.000000, + 0.000000, 6.750000, 0.000000, 1.000000;; + } + } // End of Armature_Head + Frame Armature_Leg_Left { + FrameTransformMatrix { + 1.000000, 0.000000,-0.000000, 0.000000, + -0.000000,-1.000000,-0.000000, 0.000000, + -0.000000, 0.000000,-1.000000, 0.000000, + -1.000000, 0.000000,-0.000001, 1.000000;; + } + } // End of Armature_Leg_Left + Frame Armature_Leg_Right { + FrameTransformMatrix { + 1.000000, 0.000000,-0.000000, 0.000000, + -0.000000,-1.000000,-0.000000, 0.000000, + -0.000000, 0.000000,-1.000000, 0.000000, + 1.000000, 0.000000,-0.000001, 1.000000;; + } + } // End of Armature_Leg_Right + } // End of Armature_Body + Frame Player { + FrameTransformMatrix { + 1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 1.000000;; + } + Mesh { // Player mesh + 168; + 2.000000;-1.000000;13.500000;, + -2.000000;-1.000000;13.500000;, + -2.000000;-1.000000; 6.750000;, + 2.000000;-1.000000; 6.750000;, + -2.000000;-1.000000;13.500000;, + -2.000000; 1.000000;13.500000;, + -2.000000; 1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + -2.000000; 1.000000;13.500000;, + 2.000000; 1.000000;13.500000;, + 2.000000; 1.000000; 6.750000;, + -2.000000; 1.000000; 6.750000;, + 2.000000; 1.000000; 6.750000;, + 2.000000;-1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + -2.000000; 1.000000; 6.750000;, + -2.000000; 1.000000;13.500000;, + -2.000000;-1.000000;13.500000;, + 2.000000;-1.000000;13.500000;, + 2.000000; 1.000000;13.500000;, + 0.000000; 1.000000; 6.750000;, + 0.000000; 1.000000; 0.000000;, + 0.000000;-1.000000; 0.000000;, + 0.000000;-1.000000; 6.750000;, + -2.000000;-1.000000;13.500000;, + -4.000000;-1.000000;13.500000;, + -4.000000;-1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + -2.000000; 1.000000;13.500000;, + -2.000000;-1.000000;13.500000;, + -2.000000;-1.000000; 6.750000;, + -2.000000; 1.000000; 6.750000;, + 0.000000; 1.000000; 0.000000;, + -0.000000;-1.000000; 0.000000;, + -2.000000;-1.000000; 0.000000;, + -2.000000; 1.000000; 0.000000;, + -2.000000;-1.000000; 6.750000;, + -2.000000; 1.000000; 6.750000;, + -2.000000; 1.000000; 0.000000;, + -2.000000;-1.000000; 0.000000;, + 2.000000;-2.000000;17.500000;, + -2.000000;-2.000000;17.500000;, + -2.000000;-2.000000;13.500000;, + 2.000000;-2.000000;13.500000;, + -2.000000;-2.000000;17.500000;, + -2.000000; 2.000000;17.500000;, + -2.000000; 2.000000;13.500000;, + -2.000000;-2.000000;13.500000;, + -2.000000; 2.000000;17.500000;, + 2.000000; 2.000000;17.500000;, + 2.000000; 2.000000;13.500000;, + -2.000000; 2.000000;13.500000;, + 2.000000; 2.000000;13.500000;, + 2.000000;-2.000000;13.500000;, + -2.000000;-2.000000;13.500000;, + -2.000000; 2.000000;13.500000;, + -2.000000; 2.000000;17.500000;, + -2.000000;-2.000000;17.500000;, + 2.000000;-2.000000;17.500000;, + 2.000000; 2.000000;17.500000;, + 0.000000;-1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + -2.000000;-1.000000; 0.000000;, + -0.000000;-1.000000; 0.000000;, + 2.000000; 1.000000; 6.750000;, + 2.000000; 1.000000; 0.000000;, + 0.000000; 1.000000; 0.000000;, + 0.000000; 1.000000; 6.750000;, + -2.000000; 1.000000; 6.750000;, + 0.000000; 1.000000; 6.750000;, + 0.000000; 1.000000; 0.000000;, + -2.000000; 1.000000; 0.000000;, + 2.000000; 1.000000; 6.750000;, + 4.000000; 1.000000; 6.750000;, + 4.000000;-1.000000; 6.750000;, + 2.000000;-1.000000; 6.750000;, + 4.000000; 1.000000;13.500000;, + 2.000000; 1.000000;13.500000;, + 2.000000;-1.000000;13.500000;, + 4.000000;-1.000000;13.500000;, + 0.000000;-1.000000; 6.750000;, + 0.000000;-1.000000; 0.000000;, + 2.000000;-1.000000; 0.000000;, + 2.000000;-1.000000; 6.750000;, + 0.000000; 1.000000; 6.750000;, + 0.000000;-1.000000; 6.750000;, + -0.000000;-1.000000; 0.000000;, + 0.000000; 1.000000; 0.000000;, + 2.000000;-1.000000; 6.750000;, + 2.000000;-1.000000; 0.000000;, + 2.000000; 1.000000; 0.000000;, + 2.000000; 1.000000; 6.750000;, + 2.000000;-1.000000;13.500000;, + 2.000000;-1.000000; 6.750000;, + 2.000000; 1.000000; 6.750000;, + 2.000000; 1.000000;13.500000;, + 2.000000;-2.000000;17.500000;, + 2.000000;-2.000000;13.500000;, + 2.000000; 2.000000;13.500000;, + 2.000000; 2.000000;17.500000;, + -2.000000; 1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + 0.000000;-1.000000; 6.750000;, + 0.000000; 1.000000; 6.750000;, + -4.000000; 1.000000;13.500000;, + -2.000000; 1.000000;13.500000;, + -2.000000; 1.000000; 6.750000;, + -4.000000; 1.000000; 6.750000;, + -4.000000;-1.000000;13.500000;, + -4.000000; 1.000000;13.500000;, + -4.000000; 1.000000; 6.750000;, + -4.000000;-1.000000; 6.750000;, + 4.000000;-1.000000;13.500000;, + 4.000000;-1.000000; 6.750000;, + 4.000000; 1.000000; 6.750000;, + 4.000000; 1.000000;13.500000;, + -4.000000; 1.000000;13.500000;, + -4.000000;-1.000000;13.500000;, + -2.000000;-1.000000;13.500000;, + -2.000000; 1.000000;13.500000;, + 4.000000; 1.000000;13.500000;, + 4.000000; 1.000000; 6.750000;, + 2.000000; 1.000000; 6.750000;, + 2.000000; 1.000000;13.500000;, + 0.000000; 1.000000; 0.000000;, + 2.000000; 1.000000; 0.000000;, + 2.000000;-1.000000; 0.000000;, + 0.000000;-1.000000; 0.000000;, + 2.000000; 1.000000;13.500000;, + 2.000000; 1.000000; 6.750000;, + 2.000000;-1.000000; 6.750000;, + 2.000000;-1.000000;13.500000;, + -2.000000; 1.000000; 6.750000;, + -2.000000;-1.000000; 6.750000;, + -4.000000;-1.000000; 6.750000;, + -4.000000; 1.000000; 6.750000;, + 2.000000;-1.000000;13.500000;, + 2.000000;-1.000000; 6.750000;, + 4.000000;-1.000000; 6.750000;, + 4.000000;-1.000000;13.500000;, + 2.000000; 1.000000; 6.750000;, + 0.000000; 1.000000; 6.750000;, + 0.000000;-1.000000; 6.750000;, + 2.000000;-1.000000; 6.750000;, + 2.200000;-2.200000;17.700001;, + -2.200000;-2.200000;17.700001;, + -2.200000;-2.200000;13.300000;, + 2.200000;-2.200000;13.300000;, + -2.200000;-2.200000;17.700001;, + -2.200000; 2.200000;17.700001;, + -2.200000; 2.200000;13.300000;, + -2.200000;-2.200000;13.300000;, + -2.200000; 2.200000;17.700001;, + 2.200000; 2.200000;17.700001;, + 2.200000; 2.200000;13.300000;, + -2.200000; 2.200000;13.300000;, + 2.200000; 2.200000;13.300000;, + 2.200000;-2.200000;13.300000;, + -2.200000;-2.200000;13.300000;, + -2.200000; 2.200000;13.300000;, + -2.200000; 2.200000;17.700001;, + -2.200000;-2.200000;17.700001;, + 2.200000;-2.200000;17.700001;, + 2.200000; 2.200000;17.700001;, + 2.200000;-2.200000;17.700001;, + 2.200000;-2.200000;13.300000;, + 2.200000; 2.200000;13.300000;, + 2.200000; 2.200000;17.700001;; + 42; + 4;3,2,1,0;, + 4;7,6,5,4;, + 4;11,10,9,8;, + 4;15,14,13,12;, + 4;19,18,17,16;, + 4;23,22,21,20;, + 4;27,26,25,24;, + 4;31,30,29,28;, + 4;35,34,33,32;, + 4;39,38,37,36;, + 4;43,42,41,40;, + 4;47,46,45,44;, + 4;51,50,49,48;, + 4;55,54,53,52;, + 4;59,58,57,56;, + 4;63,62,61,60;, + 4;67,66,65,64;, + 4;71,70,69,68;, + 4;75,74,73,72;, + 4;79,78,77,76;, + 4;83,82,81,80;, + 4;87,86,85,84;, + 4;91,90,89,88;, + 4;95,94,93,92;, + 4;99,98,97,96;, + 4;103,102,101,100;, + 4;107,106,105,104;, + 4;111,110,109,108;, + 4;115,114,113,112;, + 4;119,118,117,116;, + 4;123,122,121,120;, + 4;127,126,125,124;, + 4;131,130,129,128;, + 4;135,134,133,132;, + 4;139,138,137,136;, + 4;143,142,141,140;, + 4;147,146,145,144;, + 4;151,150,149,148;, + 4;155,154,153,152;, + 4;159,158,157,156;, + 4;163,162,161,160;, + 4;167,166,165,164;; + MeshTextureCoords { // Player UV coordinates + 168; + 0.625000; 0.625000;, + 0.500000; 0.625000;, + 0.500000; 1.000000;, + 0.625000; 1.000000;, + 0.500000; 0.625000;, + 0.437500; 0.625000;, + 0.437500; 1.000000;, + 0.500000; 1.000000;, + 0.437500; 0.625000;, + 0.312500; 0.625000;, + 0.312500; 1.000000;, + 0.437500; 1.000000;, + 0.562500; 0.625000;, + 0.562500; 0.500000;, + 0.437500; 0.500000;, + 0.437500; 0.625000;, + 0.437500; 0.625000;, + 0.437500; 0.500000;, + 0.312500; 0.500000;, + 0.312500; 0.625000;, + 0.187500; 0.625000;, + 0.187500; 1.000000;, + 0.125000; 1.000000;, + 0.125000; 0.625000;, + 0.812500; 0.625000;, + 0.875000; 0.625000;, + 0.875000; 1.000000;, + 0.812500; 1.000000;, + 0.750000; 0.625000;, + 0.812500; 0.625000;, + 0.812500; 1.000000;, + 0.750000; 1.000000;, + 0.187500; 0.625000;, + 0.187500; 0.500000;, + 0.125000; 0.500000;, + 0.125000; 0.625000;, + 0.000000; 0.625000;, + 0.062500; 0.625000;, + 0.062500; 1.000000;, + 0.000000; 1.000000;, + 0.500000; 0.250000;, + 0.375000; 0.250000;, + 0.375000; 0.500000;, + 0.500000; 0.500000;, + 0.375000; 0.250000;, + 0.250000; 0.250000;, + 0.250000; 0.500000;, + 0.375000; 0.500000;, + 0.250000; 0.250000;, + 0.125000; 0.250000;, + 0.125000; 0.500000;, + 0.250000; 0.500000;, + 0.375000; 0.250000;, + 0.375000; 0.000000;, + 0.250000; 0.000000;, + 0.250000; 0.250000;, + 0.250000; 0.250000;, + 0.250000; 0.000000;, + 0.125000; 0.000000;, + 0.125000; 0.250000;, + 0.250000; 0.625000;, + 0.187500; 0.625000;, + 0.187500; 1.000000;, + 0.250000; 1.000000;, + 0.125000; 0.625000;, + 0.125000; 1.000000;, + 0.062500; 1.000000;, + 0.062500; 0.625000;, + 0.125000; 0.625000;, + 0.062500; 0.625000;, + 0.062500; 1.000000;, + 0.125000; 1.000000;, + 0.750000; 0.625000;, + 0.812500; 0.625000;, + 0.812500; 0.500000;, + 0.750000; 0.500000;, + 0.687500; 0.625000;, + 0.750000; 0.625000;, + 0.750000; 0.500000;, + 0.687500; 0.500000;, + 0.250000; 0.625000;, + 0.250000; 1.000000;, + 0.187500; 1.000000;, + 0.187500; 0.625000;, + 0.187500; 0.625000;, + 0.125000; 0.625000;, + 0.125000; 1.000000;, + 0.187500; 1.000000;, + 0.000000; 0.625000;, + 0.000000; 1.000000;, + 0.062500; 1.000000;, + 0.062500; 0.625000;, + 0.250000; 0.625000;, + 0.250000; 1.000000;, + 0.312500; 1.000000;, + 0.312500; 0.625000;, + 0.000000; 0.250000;, + 0.000000; 0.500000;, + 0.125000; 0.500000;, + 0.125000; 0.250000;, + 0.125000; 0.625000;, + 0.125000; 0.500000;, + 0.062500; 0.500000;, + 0.062500; 0.625000;, + 0.687500; 0.625000;, + 0.750000; 0.625000;, + 0.750000; 1.000000;, + 0.687500; 1.000000;, + 0.687500; 0.625000;, + 0.625000; 0.625000;, + 0.625000; 1.000000;, + 0.687500; 1.000000;, + 0.687500; 0.625000;, + 0.687500; 1.000000;, + 0.625000; 1.000000;, + 0.625000; 0.625000;, + 0.687500; 0.625000;, + 0.687500; 0.500000;, + 0.750000; 0.500000;, + 0.750000; 0.625000;, + 0.687500; 0.625000;, + 0.687500; 1.000000;, + 0.750000; 1.000000;, + 0.750000; 0.625000;, + 0.187500; 0.625000;, + 0.125000; 0.625000;, + 0.125000; 0.500000;, + 0.187500; 0.500000;, + 0.750000; 0.625000;, + 0.750000; 1.000000;, + 0.812500; 1.000000;, + 0.812500; 0.625000;, + 0.750000; 0.625000;, + 0.750000; 0.500000;, + 0.812500; 0.500000;, + 0.812500; 0.625000;, + 0.812500; 0.625000;, + 0.812500; 1.000000;, + 0.875000; 1.000000;, + 0.875000; 0.625000;, + 0.125000; 0.625000;, + 0.062500; 0.625000;, + 0.062500; 0.500000;, + 0.125000; 0.500000;, + 1.000000; 0.250000;, + 0.875000; 0.250000;, + 0.875000; 0.500000;, + 1.000000; 0.500000;, + 0.875000; 0.250000;, + 0.750000; 0.250000;, + 0.750000; 0.500000;, + 0.875000; 0.500000;, + 0.750000; 0.250000;, + 0.625000; 0.250000;, + 0.625000; 0.500000;, + 0.750000; 0.500000;, + 0.875000; 0.250000;, + 0.875000; 0.000000;, + 0.750000; 0.000000;, + 0.750000; 0.250000;, + 0.750000; 0.250000;, + 0.750000; 0.000000;, + 0.625000; 0.000000;, + 0.625000; 0.250000;, + 0.500000; 0.250000;, + 0.500000; 0.500000;, + 0.625000; 0.500000;, + 0.625000; 0.250000;; + } // End of Player UV coordinates + XSkinMeshHeader { + 1; + 3; + 6; + } + SkinWeights { + "Armature_Leg_Right"; + 24; + 20, + 21, + 22, + 23, + 64, + 65, + 66, + 67, + 80, + 81, + 82, + 83, + 88, + 89, + 90, + 91, + 124, + 125, + 126, + 127, + 140, + 141, + 142, + 143; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 1.000000,-0.000000,-0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + -0.000000,-1.000000, 0.000000, 0.000000, + -1.000000, 6.750001,-0.000001, 1.000000;; + } // End of Armature_Leg_Right skin weights + SkinWeights { + "Armature_Body"; + 24; + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 92, + 93, + 94, + 95; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 1.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000,-1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + 0.000000,-6.750000,-0.000001, 1.000000;; + } // End of Armature_Body skin weights + SkinWeights { + "Armature_Arm_Right"; + 24; + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 112, + 113, + 114, + 115, + 120, + 121, + 122, + 123, + 128, + 129, + 130, + 131, + 136, + 137, + 138, + 139; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 0.989214, 0.143940, 0.027164, 0.000000, + -0.027450,-0.000000, 0.999623, 0.000000, + 0.143886,-0.989587, 0.003951, 0.000000, + -3.920884,13.071540,-0.107668, 1.000000;; + } // End of Armature_Arm_Right skin weights + SkinWeights { + "Armature_Leg_Left"; + 24; + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 60, + 61, + 62, + 63, + 68, + 69, + 70, + 71, + 84, + 85, + 86, + 87, + 100, + 101, + 102, + 103; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 1.000000,-0.000000,-0.000000, 0.000000, + 0.000000, 0.000000, 1.000000, 0.000000, + -0.000000,-1.000000, 0.000000, 0.000000, + 1.000000, 6.750001,-0.000001, 1.000000;; + } // End of Armature_Leg_Left skin weights + SkinWeights { + "Armature_Arm_Left"; + 24; + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 116, + 117, + 118, + 119, + 132, + 133, + 134, + 135; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + 0.989214,-0.143940,-0.027164, 0.000000, + 0.027450,-0.000000, 0.999623, 0.000000, + -0.143886,-0.989587, 0.003951, 0.000000, + 3.920884,13.071540,-0.107668, 1.000000;; + } // End of Armature_Arm_Left skin weights + SkinWeights { + "Armature_Head"; + 48; + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 96, + 97, + 98, + 99, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167; + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000, + 1.000000; + -1.000000, 0.000000,-0.000000, 0.000000, + -0.000000,-0.000000, 1.000000, 0.000000, + 0.000000, 1.000000, 0.000000, 0.000000, + -0.000000,-13.500000,-0.000002, 1.000000;; + } // End of Armature_Head skin weights + } // End of Player mesh + } // End of Player + } // End of Armature +} // End of Root +AnimationSet ArmatureAction { + Animation { + {Armature} + AnimationKey { // Rotation + 0; + 189; + 0;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 1;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 2;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 3;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 4;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 5;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 6;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 7;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 8;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 9;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 10;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 11;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 12;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 13;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 14;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 15;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 16;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 17;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 18;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 19;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 20;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 21;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 22;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 23;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 24;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 25;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 26;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 27;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 28;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 29;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 30;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 31;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 32;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 33;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 34;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 35;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 36;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 37;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 38;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 39;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 40;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 41;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 42;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 43;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 44;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 45;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 46;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 47;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 48;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 49;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 50;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 51;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 52;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 53;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 54;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 55;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 56;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 57;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 58;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 59;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 60;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 61;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 62;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 63;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 64;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 65;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 66;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 67;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 68;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 69;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 70;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 71;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 72;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 73;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 74;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 75;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 76;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 77;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 78;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 79;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 80;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 81;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 82;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 83;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 84;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 85;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 86;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 87;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 88;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 89;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 90;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 91;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 92;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 93;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 94;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 95;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 96;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 97;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 98;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 99;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 100;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 101;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 102;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 103;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 104;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 105;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 106;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 107;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 108;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 109;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 110;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 111;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 112;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 113;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 114;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 115;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 116;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 117;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 118;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 119;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 120;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 121;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 122;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 123;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 124;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 125;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 126;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 127;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 128;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 129;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 130;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 131;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 132;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 133;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 134;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 135;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 136;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 137;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 138;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 139;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 140;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 141;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 142;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 143;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 144;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 145;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 146;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 147;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 148;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 149;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 150;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 151;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 152;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 153;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 154;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 155;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 156;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 157;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 158;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 159;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 160;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 161;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 162;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 163;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 164;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 165;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 166;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 167;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 168;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 169;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 170;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 171;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 172;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 173;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 174;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 175;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 176;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 177;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 178;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 179;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 180;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 181;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 182;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 183;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 184;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 185;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 186;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 187;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 188;4;-1.000000, 0.000000, 0.000000, 0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3; 0.000000, 0.000000,-10.000000;;, + 1;3; 0.000000, 0.000000,-10.000000;;, + 2;3; 0.000000, 0.000000,-10.000000;;, + 3;3; 0.000000, 0.000000,-10.000000;;, + 4;3; 0.000000, 0.000000,-10.000000;;, + 5;3; 0.000000, 0.000000,-10.000000;;, + 6;3; 0.000000, 0.000000,-10.000000;;, + 7;3; 0.000000, 0.000000,-10.000000;;, + 8;3; 0.000000, 0.000000,-10.000000;;, + 9;3; 0.000000, 0.000000,-10.000000;;, + 10;3; 0.000000, 0.000000,-10.000000;;, + 11;3; 0.000000, 0.000000,-10.000000;;, + 12;3; 0.000000, 0.000000,-10.000000;;, + 13;3; 0.000000, 0.000000,-10.000000;;, + 14;3; 0.000000, 0.000000,-10.000000;;, + 15;3; 0.000000, 0.000000,-10.000000;;, + 16;3; 0.000000, 0.000000,-10.000000;;, + 17;3; 0.000000, 0.000000,-10.000000;;, + 18;3; 0.000000, 0.000000,-10.000000;;, + 19;3; 0.000000, 0.000000,-10.000000;;, + 20;3; 0.000000, 0.000000,-10.000000;;, + 21;3; 0.000000, 0.000000,-10.000000;;, + 22;3; 0.000000, 0.000000,-10.000000;;, + 23;3; 0.000000, 0.000000,-10.000000;;, + 24;3; 0.000000, 0.000000,-10.000000;;, + 25;3; 0.000000, 0.000000,-10.000000;;, + 26;3; 0.000000, 0.000000,-10.000000;;, + 27;3; 0.000000, 0.000000,-10.000000;;, + 28;3; 0.000000, 0.000000,-10.000000;;, + 29;3; 0.000000, 0.000000,-10.000000;;, + 30;3; 0.000000, 0.000000,-10.000000;;, + 31;3; 0.000000, 0.000000,-10.000000;;, + 32;3; 0.000000, 0.000000,-10.000000;;, + 33;3; 0.000000, 0.000000,-10.000000;;, + 34;3; 0.000000, 0.000000,-10.000000;;, + 35;3; 0.000000, 0.000000,-10.000000;;, + 36;3; 0.000000, 0.000000,-10.000000;;, + 37;3; 0.000000, 0.000000,-10.000000;;, + 38;3; 0.000000, 0.000000,-10.000000;;, + 39;3; 0.000000, 0.000000,-10.000000;;, + 40;3; 0.000000, 0.000000,-10.000000;;, + 41;3; 0.000000, 0.000000,-10.000000;;, + 42;3; 0.000000, 0.000000,-10.000000;;, + 43;3; 0.000000, 0.000000,-10.000000;;, + 44;3; 0.000000, 0.000000,-10.000000;;, + 45;3; 0.000000, 0.000000,-10.000000;;, + 46;3; 0.000000, 0.000000,-10.000000;;, + 47;3; 0.000000, 0.000000,-10.000000;;, + 48;3; 0.000000, 0.000000,-10.000000;;, + 49;3; 0.000000, 0.000000,-10.000000;;, + 50;3; 0.000000, 0.000000,-10.000000;;, + 51;3; 0.000000, 0.000000,-10.000000;;, + 52;3; 0.000000, 0.000000,-10.000000;;, + 53;3; 0.000000, 0.000000,-10.000000;;, + 54;3; 0.000000, 0.000000,-10.000000;;, + 55;3; 0.000000, 0.000000,-10.000000;;, + 56;3; 0.000000, 0.000000,-10.000000;;, + 57;3; 0.000000, 0.000000,-10.000000;;, + 58;3; 0.000000, 0.000000,-10.000000;;, + 59;3; 0.000000, 0.000000,-10.000000;;, + 60;3; 0.000000, 0.000000,-10.000000;;, + 61;3; 0.000000, 0.000000,-10.000000;;, + 62;3; 0.000000, 0.000000,-10.000000;;, + 63;3; 0.000000, 0.000000,-10.000000;;, + 64;3; 0.000000, 0.000000,-10.000000;;, + 65;3; 0.000000, 0.000000,-10.000000;;, + 66;3; 0.000000, 0.000000,-10.000000;;, + 67;3; 0.000000, 0.000000,-10.000000;;, + 68;3; 0.000000, 0.000000,-10.000000;;, + 69;3; 0.000000, 0.000000,-10.000000;;, + 70;3; 0.000000, 0.000000,-10.000000;;, + 71;3; 0.000000, 0.000000,-10.000000;;, + 72;3; 0.000000, 0.000000,-10.000000;;, + 73;3; 0.000000, 0.000000,-10.000000;;, + 74;3; 0.000000, 0.000000,-10.000000;;, + 75;3; 0.000000, 0.000000,-10.000000;;, + 76;3; 0.000000, 0.000000,-10.000000;;, + 77;3; 0.000000, 0.000000,-10.000000;;, + 78;3; 0.000000, 0.000000,-10.000000;;, + 79;3; 0.000000, 0.000000,-10.000000;;, + 80;3; 0.000000, 0.000000,-10.000000;;, + 81;3; 0.000000, 0.000000,-10.000000;;, + 82;3; 0.000000, 0.000000,-10.000000;;, + 83;3; 0.000000, 0.000000,-10.000000;;, + 84;3; 0.000000, 0.000000,-10.000000;;, + 85;3; 0.000000, 0.000000,-10.000000;;, + 86;3; 0.000000, 0.000000,-10.000000;;, + 87;3; 0.000000, 0.000000,-10.000000;;, + 88;3; 0.000000, 0.000000,-10.000000;;, + 89;3; 0.000000, 0.000000,-10.000000;;, + 90;3; 0.000000, 0.000000,-10.000000;;, + 91;3; 0.000000, 0.000000,-10.000000;;, + 92;3; 0.000000, 0.000000,-10.000000;;, + 93;3; 0.000000, 0.000000,-10.000000;;, + 94;3; 0.000000, 0.000000,-10.000000;;, + 95;3; 0.000000, 0.000000,-10.000000;;, + 96;3; 0.000000, 0.000000,-10.000000;;, + 97;3; 0.000000, 0.000000,-10.000000;;, + 98;3; 0.000000, 0.000000,-10.000000;;, + 99;3; 0.000000, 0.000000,-10.000000;;, + 100;3; 0.000000, 0.000000,-10.000000;;, + 101;3; 0.000000, 0.000000,-10.000000;;, + 102;3; 0.000000, 0.000000,-10.000000;;, + 103;3; 0.000000, 0.000000,-10.000000;;, + 104;3; 0.000000, 0.000000,-10.000000;;, + 105;3; 0.000000, 0.000000,-10.000000;;, + 106;3; 0.000000, 0.000000,-10.000000;;, + 107;3; 0.000000, 0.000000,-10.000000;;, + 108;3; 0.000000, 0.000000,-10.000000;;, + 109;3; 0.000000, 0.000000,-10.000000;;, + 110;3; 0.000000, 0.000000,-10.000000;;, + 111;3; 0.000000, 0.000000,-10.000000;;, + 112;3; 0.000000, 0.000000,-10.000000;;, + 113;3; 0.000000, 0.000000,-10.000000;;, + 114;3; 0.000000, 0.000000,-10.000000;;, + 115;3; 0.000000, 0.000000,-10.000000;;, + 116;3; 0.000000, 0.000000,-10.000000;;, + 117;3; 0.000000, 0.000000,-10.000000;;, + 118;3; 0.000000, 0.000000,-10.000000;;, + 119;3; 0.000000, 0.000000,-10.000000;;, + 120;3; 0.000000, 0.000000,-10.000000;;, + 121;3; 0.000000, 0.000000,-10.000000;;, + 122;3; 0.000000, 0.000000,-10.000000;;, + 123;3; 0.000000, 0.000000,-10.000000;;, + 124;3; 0.000000, 0.000000,-10.000000;;, + 125;3; 0.000000, 0.000000,-10.000000;;, + 126;3; 0.000000, 0.000000,-10.000000;;, + 127;3; 0.000000, 0.000000,-10.000000;;, + 128;3; 0.000000, 0.000000,-10.000000;;, + 129;3; 0.000000, 0.000000,-10.000000;;, + 130;3; 0.000000, 0.000000,-10.000000;;, + 131;3; 0.000000, 0.000000,-10.000000;;, + 132;3; 0.000000, 0.000000,-10.000000;;, + 133;3; 0.000000, 0.000000,-10.000000;;, + 134;3; 0.000000, 0.000000,-10.000000;;, + 135;3; 0.000000, 0.000000,-10.000000;;, + 136;3; 0.000000, 0.000000,-10.000000;;, + 137;3; 0.000000, 0.000000,-10.000000;;, + 138;3; 0.000000, 0.000000,-10.000000;;, + 139;3; 0.000000, 0.000000,-10.000000;;, + 140;3; 0.000000, 0.000000,-10.000000;;, + 141;3; 0.000000, 0.000000,-10.000000;;, + 142;3; 0.000000, 0.000000,-10.000000;;, + 143;3; 0.000000, 0.000000,-10.000000;;, + 144;3; 0.000000, 0.000000,-10.000000;;, + 145;3; 0.000000, 0.000000,-10.000000;;, + 146;3; 0.000000, 0.000000,-10.000000;;, + 147;3; 0.000000, 0.000000,-10.000000;;, + 148;3; 0.000000, 0.000000,-10.000000;;, + 149;3; 0.000000, 0.000000,-10.000000;;, + 150;3; 0.000000, 0.000000,-10.000000;;, + 151;3; 0.000000, 0.000000,-10.000000;;, + 152;3; 0.000000, 0.000000,-10.000000;;, + 153;3; 0.000000, 0.000000,-10.000000;;, + 154;3; 0.000000, 0.000000,-10.000000;;, + 155;3; 0.000000, 0.000000,-10.000000;;, + 156;3; 0.000000, 0.000000,-10.000000;;, + 157;3; 0.000000, 0.000000,-10.000000;;, + 158;3; 0.000000, 0.000000,-10.000000;;, + 159;3; 0.000000, 0.000000,-10.000000;;, + 160;3; 0.000000, 0.000000,-10.000000;;, + 161;3; 0.000000, 0.000000,-10.000000;;, + 162;3; 0.000000, 0.000000,-10.000000;;, + 163;3; 0.000000, 0.000000,-10.000000;;, + 164;3; 0.000000, 0.000000,-10.000000;;, + 165;3; 0.000000, 0.000000,-10.000000;;, + 166;3; 0.000000, 0.000000,-10.000000;;, + 167;3; 0.000000, 0.000000,-10.000000;;, + 168;3; 0.000000, 0.000000,-10.000000;;, + 169;3; 0.000000, 0.000000,-10.000000;;, + 170;3; 0.000000, 0.000000,-10.000000;;, + 171;3; 0.000000, 0.000000,-10.000000;;, + 172;3; 0.000000, 0.000000,-10.000000;;, + 173;3; 0.000000, 0.000000,-10.000000;;, + 174;3; 0.000000, 0.000000,-10.000000;;, + 175;3; 0.000000, 0.000000,-10.000000;;, + 176;3; 0.000000, 0.000000,-10.000000;;, + 177;3; 0.000000, 0.000000,-10.000000;;, + 178;3; 0.000000, 0.000000,-10.000000;;, + 179;3; 0.000000, 0.000000,-10.000000;;, + 180;3; 0.000000, 0.000000,-10.000000;;, + 181;3; 0.000000, 0.000000,-10.000000;;, + 182;3; 0.000000, 0.000000,-10.000000;;, + 183;3; 0.000000, 0.000000,-10.000000;;, + 184;3; 0.000000, 0.000000,-10.000000;;, + 185;3; 0.000000, 0.000000,-10.000000;;, + 186;3; 0.000000, 0.000000,-10.000000;;, + 187;3; 0.000000, 0.000000,-10.000000;;, + 188;3; 0.000000, 0.000000,-10.000000;;; + } + } + Animation { + {Armature_Body} + AnimationKey { // Rotation + 0; + 189; + 0;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 1;4;-0.706933, 0.707273, 0.000000, 0.000000;;, + 2;4;-0.706408, 0.707776, 0.000000, 0.000000;;, + 3;4;-0.705530, 0.708616, 0.000000, 0.000000;;, + 4;4;-0.704305, 0.709789, 0.000000, 0.000000;;, + 5;4;-0.702749, 0.711279, 0.000000, 0.000000;;, + 6;4;-0.700886, 0.713062, 0.000000, 0.000000;;, + 7;4;-0.698758, 0.715099, 0.000000, 0.000000;;, + 8;4;-0.696414, 0.717343, 0.000000, 0.000000;;, + 9;4;-0.693920, 0.719730, 0.000000, 0.000000;;, + 10;4;-0.691348, 0.722192, 0.000000, 0.000000;;, + 11;4;-0.688777, 0.724654, 0.000000, 0.000000;;, + 12;4;-0.686283, 0.727042, 0.000000, 0.000000;;, + 13;4;-0.683939, 0.729285, 0.000000, 0.000000;;, + 14;4;-0.681811, 0.731323, 0.000000, 0.000000;;, + 15;4;-0.679949, 0.733105, 0.000000, 0.000000;;, + 16;4;-0.678392, 0.734596, 0.000000, 0.000000;;, + 17;4;-0.677167, 0.735768, 0.000000, 0.000000;;, + 18;4;-0.676289, 0.736609, 0.000000, 0.000000;;, + 19;4;-0.675764, 0.737111, 0.000000, 0.000000;;, + 20;4;-0.675590, 0.737277, 0.000000, 0.000000;;, + 21;4;-0.675764, 0.737111, 0.000000, 0.000000;;, + 22;4;-0.676289, 0.736609, 0.000000, 0.000000;;, + 23;4;-0.677167, 0.735768, 0.000000, 0.000000;;, + 24;4;-0.678392, 0.734596, 0.000000, 0.000000;;, + 25;4;-0.679949, 0.733105, 0.000000, 0.000000;;, + 26;4;-0.681811, 0.731323, 0.000000, 0.000000;;, + 27;4;-0.683939, 0.729285, 0.000000, 0.000000;;, + 28;4;-0.686283, 0.727042, 0.000000, 0.000000;;, + 29;4;-0.688777, 0.724654, 0.000000, 0.000000;;, + 30;4;-0.691349, 0.722192, 0.000000, 0.000000;;, + 31;4;-0.693920, 0.719730, 0.000000, 0.000000;;, + 32;4;-0.696415, 0.717343, 0.000000, 0.000000;;, + 33;4;-0.698758, 0.715099, 0.000000, 0.000000;;, + 34;4;-0.700886, 0.713062, 0.000000, 0.000000;;, + 35;4;-0.702749, 0.711279, 0.000000, 0.000000;;, + 36;4;-0.704305, 0.709789, 0.000000, 0.000000;;, + 37;4;-0.705530, 0.708616, 0.000000, 0.000000;;, + 38;4;-0.706408, 0.707776, 0.000000, 0.000000;;, + 39;4;-0.706933, 0.707273, 0.000000, 0.000000;;, + 40;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 41;4;-0.706933, 0.707273, 0.000000, 0.000000;;, + 42;4;-0.706408, 0.707776, 0.000000, 0.000000;;, + 43;4;-0.705530, 0.708616, 0.000000, 0.000000;;, + 44;4;-0.704305, 0.709789, 0.000000, 0.000000;;, + 45;4;-0.702749, 0.711279, 0.000000, 0.000000;;, + 46;4;-0.700886, 0.713062, 0.000000, 0.000000;;, + 47;4;-0.698758, 0.715099, 0.000000, 0.000000;;, + 48;4;-0.696415, 0.717343, 0.000000, 0.000000;;, + 49;4;-0.693920, 0.719730, 0.000000, 0.000000;;, + 50;4;-0.691348, 0.722192, 0.000000, 0.000000;;, + 51;4;-0.688777, 0.724654, 0.000000, 0.000000;;, + 52;4;-0.686283, 0.727042, 0.000000, 0.000000;;, + 53;4;-0.683939, 0.729285, 0.000000, 0.000000;;, + 54;4;-0.681811, 0.731323, 0.000000, 0.000000;;, + 55;4;-0.679949, 0.733105, 0.000000, 0.000000;;, + 56;4;-0.678392, 0.734596, 0.000000, 0.000000;;, + 57;4;-0.677167, 0.735768, 0.000000, 0.000000;;, + 58;4;-0.676289, 0.736609, 0.000000, 0.000000;;, + 59;4;-0.675764, 0.737111, 0.000000, 0.000000;;, + 60;4;-0.675590, 0.737277, 0.000000, 0.000000;;, + 61;4;-0.675754, 0.737121, 0.000000, 0.000000;;, + 62;4;-0.676212, 0.736682, 0.000000, 0.000000;;, + 63;4;-0.676927, 0.735998, 0.000000, 0.000000;;, + 64;4;-0.677865, 0.735100, 0.000000, 0.000000;;, + 65;4;-0.679001, 0.734013, 0.000000, 0.000000;;, + 66;4;-0.680312, 0.732757, 0.000000, 0.000000;;, + 67;4;-0.681779, 0.731353, 0.000000, 0.000000;;, + 68;4;-0.683387, 0.729813, 0.000000, 0.000000;;, + 69;4;-0.685120, 0.728154, 0.000000, 0.000000;;, + 70;4;-0.686966, 0.726388, 0.000000, 0.000000;;, + 71;4;-0.688910, 0.724526, 0.000000, 0.000000;;, + 72;4;-0.690941, 0.722582, 0.000000, 0.000000;;, + 73;4;-0.693046, 0.720567, 0.000000, 0.000000;;, + 74;4;-0.695210, 0.718495, 0.000000, 0.000000;;, + 75;4;-0.697417, 0.716383, 0.000000, 0.000000;;, + 76;4;-0.699643, 0.714252, 0.000000, 0.000000;;, + 77;4;-0.701856, 0.712133, 0.000000, 0.000000;;, + 78;4;-0.703995, 0.710086, 0.000000, 0.000000;;, + 79;4;-0.705928, 0.708235, 0.000000, 0.000000;;, + 80;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 81;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 82;4;-0.705928, 0.708235, 0.000000, 0.000000;;, + 83;4;-0.703995, 0.710086, 0.000000, 0.000000;;, + 84;4;-0.701856, 0.712133, 0.000000, 0.000000;;, + 85;4;-0.699643, 0.714252, 0.000000, 0.000000;;, + 86;4;-0.697417, 0.716383, 0.000000, 0.000000;;, + 87;4;-0.695210, 0.718495, 0.000000, 0.000000;;, + 88;4;-0.693046, 0.720567, 0.000000, 0.000000;;, + 89;4;-0.690941, 0.722582, 0.000000, 0.000000;;, + 90;4;-0.688910, 0.724526, 0.000000, 0.000000;;, + 91;4;-0.686966, 0.726388, 0.000000, 0.000000;;, + 92;4;-0.685120, 0.728154, 0.000000, 0.000000;;, + 93;4;-0.683387, 0.729813, 0.000000, 0.000000;;, + 94;4;-0.681779, 0.731353, 0.000000, 0.000000;;, + 95;4;-0.680312, 0.732758, 0.000000, 0.000000;;, + 96;4;-0.679001, 0.734013, 0.000000, 0.000000;;, + 97;4;-0.677865, 0.735100, 0.000000, 0.000000;;, + 98;4;-0.676927, 0.735998, 0.000000, 0.000000;;, + 99;4;-0.676212, 0.736682, 0.000000, 0.000000;;, + 100;4;-0.675754, 0.737121, 0.000000, 0.000000;;, + 101;4;-0.675590, 0.737277, 0.000000, 0.000000;;, + 102;4;-0.675764, 0.737111, 0.000000, 0.000000;;, + 103;4;-0.676289, 0.736609, 0.000000, 0.000000;;, + 104;4;-0.677167, 0.735768, 0.000000, 0.000000;;, + 105;4;-0.678392, 0.734596, 0.000000, 0.000000;;, + 106;4;-0.679949, 0.733105, 0.000000, 0.000000;;, + 107;4;-0.681811, 0.731323, 0.000000, 0.000000;;, + 108;4;-0.683939, 0.729285, 0.000000, 0.000000;;, + 109;4;-0.686283, 0.727042, 0.000000, 0.000000;;, + 110;4;-0.688777, 0.724654, 0.000000, 0.000000;;, + 111;4;-0.691348, 0.722192, 0.000000, 0.000000;;, + 112;4;-0.693920, 0.719730, 0.000000, 0.000000;;, + 113;4;-0.696415, 0.717343, 0.000000, 0.000000;;, + 114;4;-0.698758, 0.715099, 0.000000, 0.000000;;, + 115;4;-0.700886, 0.713062, 0.000000, 0.000000;;, + 116;4;-0.702749, 0.711279, 0.000000, 0.000000;;, + 117;4;-0.704305, 0.709789, 0.000000, 0.000000;;, + 118;4;-0.705530, 0.708616, 0.000000, 0.000000;;, + 119;4;-0.706408, 0.707776, 0.000000, 0.000000;;, + 120;4;-0.706933, 0.707273, 0.000000, 0.000000;;, + 121;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 122;4;-0.706933, 0.707273, 0.000000, 0.000000;;, + 123;4;-0.706408, 0.707776, 0.000000, 0.000000;;, + 124;4;-0.705530, 0.708616, 0.000000, 0.000000;;, + 125;4;-0.704305, 0.709789, 0.000000, 0.000000;;, + 126;4;-0.702749, 0.711279, 0.000000, 0.000000;;, + 127;4;-0.700886, 0.713062, 0.000000, 0.000000;;, + 128;4;-0.698758, 0.715099, 0.000000, 0.000000;;, + 129;4;-0.696415, 0.717343, 0.000000, 0.000000;;, + 130;4;-0.693920, 0.719730, 0.000000, 0.000000;;, + 131;4;-0.691348, 0.722192, 0.000000, 0.000000;;, + 132;4;-0.688777, 0.724654, 0.000000, 0.000000;;, + 133;4;-0.686283, 0.727042, 0.000000, 0.000000;;, + 134;4;-0.683939, 0.729285, 0.000000, 0.000000;;, + 135;4;-0.681811, 0.731323, 0.000000, 0.000000;;, + 136;4;-0.679949, 0.733105, 0.000000, 0.000000;;, + 137;4;-0.678392, 0.734596, 0.000000, 0.000000;;, + 138;4;-0.677167, 0.735768, 0.000000, 0.000000;;, + 139;4;-0.676289, 0.736609, 0.000000, 0.000000;;, + 140;4;-0.675764, 0.737111, 0.000000, 0.000000;;, + 141;4;-0.675590, 0.737277, 0.000000, 0.000000;;, + 142;4;-0.675754, 0.737121, 0.000000, 0.000000;;, + 143;4;-0.676211, 0.736683, 0.000000, 0.000000;;, + 144;4;-0.676923, 0.736001, 0.000000, 0.000000;;, + 145;4;-0.677857, 0.735107, 0.000000, 0.000000;;, + 146;4;-0.678987, 0.734026, 0.000000, 0.000000;;, + 147;4;-0.680291, 0.732778, 0.000000, 0.000000;;, + 148;4;-0.681750, 0.731381, 0.000000, 0.000000;;, + 149;4;-0.683349, 0.729852, 0.000000, 0.000000;;, + 150;4;-0.685071, 0.728203, 0.000000, 0.000000;;, + 151;4;-0.686905, 0.726448, 0.000000, 0.000000;;, + 152;4;-0.688838, 0.724598, 0.000000, 0.000000;;, + 153;4;-0.690858, 0.722664, 0.000000, 0.000000;;, + 154;4;-0.692953, 0.720659, 0.000000, 0.000000;;, + 155;4;-0.695109, 0.718596, 0.000000, 0.000000;;, + 156;4;-0.697310, 0.716489, 0.000000, 0.000000;;, + 157;4;-0.699536, 0.714358, 0.000000, 0.000000;;, + 158;4;-0.701753, 0.712235, 0.000000, 0.000000;;, + 159;4;-0.703909, 0.710171, 0.000000, 0.000000;;, + 160;4;-0.705875, 0.708288, 0.000000, 0.000000;;, + 161;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 162;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 163;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 164;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 165;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 166;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 167;4;-0.000000, 1.000000, 0.000000, 0.000000;;, + 168;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 169;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 170;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 171;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 172;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 173;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 174;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 175;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 176;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 177;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 178;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 179;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 180;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 181;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 182;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 183;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 184;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 185;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 186;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 187;4;-0.707107, 0.707107, 0.000000, 0.000000;;, + 188;4;-0.707107, 0.707107, 0.000000, 0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3;-0.000000, 0.000000, 6.750000;;, + 1;3;-0.000000, 0.000000, 6.750000;;, + 2;3;-0.000000, 0.000000, 6.750000;;, + 3;3;-0.000000, 0.000000, 6.750000;;, + 4;3;-0.000000, 0.000000, 6.750000;;, + 5;3;-0.000000, 0.000000, 6.750000;;, + 6;3;-0.000000, 0.000000, 6.750000;;, + 7;3;-0.000000, 0.000000, 6.750000;;, + 8;3;-0.000000, 0.000000, 6.750000;;, + 9;3;-0.000000, 0.000000, 6.750000;;, + 10;3;-0.000000, 0.000000, 6.750000;;, + 11;3;-0.000000, 0.000000, 6.750000;;, + 12;3;-0.000000, 0.000000, 6.750000;;, + 13;3;-0.000000, 0.000000, 6.750000;;, + 14;3;-0.000000, 0.000000, 6.750000;;, + 15;3;-0.000000, 0.000000, 6.750000;;, + 16;3;-0.000000, 0.000000, 6.750000;;, + 17;3;-0.000000, 0.000000, 6.750000;;, + 18;3;-0.000000, 0.000000, 6.750000;;, + 19;3;-0.000000, 0.000000, 6.750000;;, + 20;3;-0.000000, 0.000000, 6.750000;;, + 21;3;-0.000000, 0.000000, 6.750000;;, + 22;3;-0.000000, 0.000000, 6.750000;;, + 23;3;-0.000000, 0.000000, 6.750000;;, + 24;3;-0.000000, 0.000000, 6.750000;;, + 25;3;-0.000000, 0.000000, 6.750000;;, + 26;3;-0.000000, 0.000000, 6.750000;;, + 27;3;-0.000000, 0.000000, 6.750000;;, + 28;3;-0.000000, 0.000000, 6.750000;;, + 29;3;-0.000000, 0.000000, 6.750000;;, + 30;3;-0.000000, 0.000000, 6.750000;;, + 31;3;-0.000000, 0.000000, 6.750000;;, + 32;3;-0.000000, 0.000000, 6.750000;;, + 33;3;-0.000000, 0.000000, 6.750000;;, + 34;3;-0.000000, 0.000000, 6.750000;;, + 35;3;-0.000000, 0.000000, 6.750000;;, + 36;3;-0.000000, 0.000000, 6.750000;;, + 37;3;-0.000000, 0.000000, 6.750000;;, + 38;3;-0.000000, 0.000000, 6.750000;;, + 39;3;-0.000000, 0.000000, 6.750000;;, + 40;3;-0.000000, 0.000000, 6.750000;;, + 41;3;-0.000000, 0.000000, 6.750000;;, + 42;3;-0.000000, 0.000000, 6.750000;;, + 43;3;-0.000000, 0.000000, 6.750000;;, + 44;3;-0.000000, 0.000000, 6.750000;;, + 45;3;-0.000000, 0.000000, 6.750000;;, + 46;3;-0.000000, 0.000000, 6.750000;;, + 47;3;-0.000000, 0.000000, 6.750000;;, + 48;3;-0.000000, 0.000000, 6.750000;;, + 49;3;-0.000000, 0.000000, 6.750000;;, + 50;3;-0.000000, 0.000000, 6.750000;;, + 51;3;-0.000000, 0.000000, 6.750000;;, + 52;3;-0.000000, 0.000000, 6.750000;;, + 53;3;-0.000000, 0.000000, 6.750000;;, + 54;3;-0.000000, 0.000000, 6.750000;;, + 55;3;-0.000000, 0.000000, 6.750000;;, + 56;3;-0.000000, 0.000000, 6.750000;;, + 57;3;-0.000000, 0.000000, 6.750000;;, + 58;3;-0.000000, 0.000000, 6.750000;;, + 59;3;-0.000000, 0.000000, 6.750000;;, + 60;3;-0.000000, 0.000000, 6.750000;;, + 61;3;-0.000000, 0.000000, 6.750000;;, + 62;3;-0.000000, 0.000000, 6.750000;;, + 63;3;-0.000000, 0.000000, 6.750000;;, + 64;3;-0.000000, 0.000000, 6.750000;;, + 65;3;-0.000000, 0.000000, 6.750000;;, + 66;3;-0.000000, 0.000000, 6.750000;;, + 67;3;-0.000000, 0.000000, 6.750000;;, + 68;3;-0.000000, 0.000000, 6.750000;;, + 69;3;-0.000000, 0.000000, 6.750000;;, + 70;3;-0.000000, 0.000000, 6.750000;;, + 71;3;-0.000000, 0.000000, 6.750000;;, + 72;3;-0.000000, 0.000000, 6.750000;;, + 73;3;-0.000000, 0.000000, 6.750000;;, + 74;3;-0.000000, 0.000000, 6.750000;;, + 75;3;-0.000000, 0.000000, 6.750000;;, + 76;3;-0.000000, 0.000000, 6.750000;;, + 77;3;-0.000000, 0.000000, 6.750000;;, + 78;3;-0.000000, 0.000000, 6.750000;;, + 79;3;-0.000000, 0.000000, 6.750000;;, + 80;3;-0.000000, 0.000000, 6.750000;;, + 81;3;-0.000000, 0.000000, 1.000000;;, + 82;3;-0.000000, 0.000000, 1.000000;;, + 83;3;-0.000000, 0.000000, 1.000000;;, + 84;3;-0.000000, 0.000000, 1.000000;;, + 85;3;-0.000000, 0.000000, 1.000000;;, + 86;3;-0.000000, 0.000000, 1.000000;;, + 87;3;-0.000000, 0.000000, 1.000000;;, + 88;3;-0.000000, 0.000000, 1.000000;;, + 89;3;-0.000000, 0.000000, 1.000000;;, + 90;3;-0.000000, 0.000000, 1.000000;;, + 91;3;-0.000000, 0.000000, 1.000000;;, + 92;3;-0.000000, 0.000000, 1.000000;;, + 93;3;-0.000000, 0.000000, 1.000000;;, + 94;3;-0.000000, 0.000000, 1.000000;;, + 95;3;-0.000000, 0.000000, 1.000000;;, + 96;3;-0.000000, 0.000000, 1.000000;;, + 97;3;-0.000000, 0.000000, 1.000000;;, + 98;3;-0.000000, 0.000000, 1.000000;;, + 99;3;-0.000000, 0.000000, 1.000000;;, + 100;3;-0.000000, 0.000000, 1.000000;;, + 101;3;-0.000000, 0.000000, 1.000000;;, + 102;3;-0.000000, 0.000000, 1.000000;;, + 103;3;-0.000000, 0.000000, 1.000000;;, + 104;3;-0.000000, 0.000000, 1.000000;;, + 105;3;-0.000000, 0.000000, 1.000000;;, + 106;3;-0.000000, 0.000000, 1.000000;;, + 107;3;-0.000000, 0.000000, 1.000000;;, + 108;3;-0.000000, 0.000000, 1.000000;;, + 109;3;-0.000000, 0.000000, 1.000000;;, + 110;3;-0.000000, 0.000000, 1.000000;;, + 111;3;-0.000000, 0.000000, 1.000000;;, + 112;3;-0.000000, 0.000000, 1.000000;;, + 113;3;-0.000000, 0.000000, 1.000000;;, + 114;3;-0.000000, 0.000000, 1.000000;;, + 115;3;-0.000000, 0.000000, 1.000000;;, + 116;3;-0.000000, 0.000000, 1.000000;;, + 117;3;-0.000000, 0.000000, 1.000000;;, + 118;3;-0.000000, 0.000000, 1.000000;;, + 119;3;-0.000000, 0.000000, 1.000000;;, + 120;3;-0.000000, 0.000000, 1.000000;;, + 121;3;-0.000000, 0.000000, 1.000000;;, + 122;3;-0.000000, 0.000000, 1.000000;;, + 123;3;-0.000000, 0.000000, 1.000000;;, + 124;3;-0.000000, 0.000000, 1.000000;;, + 125;3;-0.000000, 0.000000, 1.000000;;, + 126;3;-0.000000, 0.000000, 1.000000;;, + 127;3;-0.000000, 0.000000, 1.000000;;, + 128;3;-0.000000, 0.000000, 1.000000;;, + 129;3;-0.000000, 0.000000, 1.000000;;, + 130;3;-0.000000, 0.000000, 1.000000;;, + 131;3;-0.000000, 0.000000, 1.000000;;, + 132;3;-0.000000, 0.000000, 1.000000;;, + 133;3;-0.000000, 0.000000, 1.000000;;, + 134;3;-0.000000, 0.000000, 1.000000;;, + 135;3;-0.000000, 0.000000, 1.000000;;, + 136;3;-0.000000, 0.000000, 1.000000;;, + 137;3;-0.000000, 0.000000, 1.000000;;, + 138;3;-0.000000, 0.000000, 1.000000;;, + 139;3;-0.000000, 0.000000, 1.000000;;, + 140;3;-0.000000, 0.000000, 1.000000;;, + 141;3;-0.000000, 0.000000, 1.000000;;, + 142;3;-0.000000, 0.000000, 1.000000;;, + 143;3;-0.000000, 0.000000, 1.000000;;, + 144;3;-0.000000, 0.000000, 1.000000;;, + 145;3;-0.000000, 0.000000, 1.000000;;, + 146;3;-0.000000, 0.000000, 1.000000;;, + 147;3;-0.000000, 0.000000, 1.000000;;, + 148;3;-0.000000, 0.000000, 1.000000;;, + 149;3;-0.000000, 0.000000, 1.000000;;, + 150;3;-0.000000, 0.000000, 1.000000;;, + 151;3;-0.000000, 0.000000, 1.000000;;, + 152;3;-0.000000, 0.000000, 1.000000;;, + 153;3;-0.000000, 0.000000, 1.000000;;, + 154;3;-0.000000, 0.000000, 1.000000;;, + 155;3;-0.000000, 0.000000, 1.000000;;, + 156;3;-0.000000, 0.000000, 1.000000;;, + 157;3;-0.000000, 0.000000, 1.000000;;, + 158;3;-0.000000, 0.000000, 1.000000;;, + 159;3;-0.000000, 0.000000, 1.000000;;, + 160;3;-0.000000, 0.000000, 1.000000;;, + 161;3;-0.000000, 0.000000, 1.000000;;, + 162;3;-0.000000, 2.000001, 1.000000;;, + 163;3;-0.000000, 2.000001, 1.000000;;, + 164;3;-0.000000, 2.000001, 1.000000;;, + 165;3;-0.000000, 2.000001, 1.000000;;, + 166;3;-0.000000, 2.000001, 1.000000;;, + 167;3;-0.000000, 2.000001, 1.000000;;, + 168;3;-0.000000, 0.000000, 6.750000;;, + 169;3;-0.000000, 0.000000, 6.750000;;, + 170;3;-0.000000, 0.000000, 6.750000;;, + 171;3;-0.000000, 0.000000, 6.750000;;, + 172;3;-0.000000, 0.000000, 6.750000;;, + 173;3;-0.000000, 0.000000, 6.750000;;, + 174;3;-0.000000, 0.000000, 6.750000;;, + 175;3;-0.000000, 0.000000, 6.750000;;, + 176;3;-0.000000, 0.000000, 6.750000;;, + 177;3;-0.000000, 0.000000, 6.750000;;, + 178;3;-0.000000, 0.000000, 6.750000;;, + 179;3;-0.000000, 0.000000, 6.750000;;, + 180;3;-0.000000, 0.000000, 6.750000;;, + 181;3;-0.000000, 0.000000, 6.750000;;, + 182;3;-0.000000, 0.000000, 6.750000;;, + 183;3;-0.000000, 0.000000, 6.750000;;, + 184;3;-0.000000, 0.000000, 6.750000;;, + 185;3;-0.000000, 0.000000, 6.750000;;, + 186;3;-0.000000, 0.000000, 6.750000;;, + 187;3;-0.000000, 0.000000, 6.750000;;, + 188;3;-0.000000, 0.000000, 6.750000;;; + } + } + Animation { + {Armature_Head} + AnimationKey { // Rotation + 0; + 189; + 0;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 1;4;-0.000120,-0.000005, 0.999993,-0.000240;;, + 2;4;-0.000483,-0.000021, 0.999974,-0.000967;;, + 3;4;-0.001090,-0.000048, 0.999941,-0.002181;;, + 4;4;-0.001937,-0.000085, 0.999894,-0.003876;;, + 5;4;-0.003014,-0.000132, 0.999835,-0.006030;;, + 6;4;-0.004301,-0.000188, 0.999765,-0.008607;;, + 7;4;-0.005773,-0.000252, 0.999685,-0.011553;;, + 8;4;-0.007394,-0.000323, 0.999596,-0.014795;;, + 9;4;-0.009118,-0.000398, 0.999502,-0.018246;;, + 10;4;-0.010897,-0.000476, 0.999405,-0.021804;;, + 11;4;-0.012675,-0.000553, 0.999308,-0.025363;;, + 12;4;-0.014400,-0.000629, 0.999214,-0.028814;;, + 13;4;-0.016021,-0.000699, 0.999126,-0.032056;;, + 14;4;-0.017493,-0.000764, 0.999045,-0.035002;;, + 15;4;-0.018780,-0.000820, 0.998975,-0.037578;;, + 16;4;-0.019857,-0.000867, 0.998916,-0.039733;;, + 17;4;-0.020704,-0.000904, 0.998870,-0.041427;;, + 18;4;-0.021311,-0.000930, 0.998837,-0.042642;;, + 19;4;-0.021674,-0.000946, 0.998817,-0.043369;;, + 20;4;-0.021794,-0.000952, 0.998811,-0.043609;;, + 21;4;-0.021720,-0.000948, 0.998817,-0.043369;;, + 22;4;-0.021494,-0.000938, 0.998837,-0.042642;;, + 23;4;-0.021108,-0.000922, 0.998870,-0.041427;;, + 24;4;-0.020560,-0.000898, 0.998916,-0.039733;;, + 25;4;-0.019848,-0.000867, 0.998975,-0.037578;;, + 26;4;-0.018975,-0.000828, 0.999045,-0.035002;;, + 27;4;-0.017947,-0.000784, 0.999126,-0.032056;;, + 28;4;-0.016778,-0.000733, 0.999214,-0.028814;;, + 29;4;-0.015484,-0.000676, 0.999308,-0.025363;;, + 30;4;-0.014088,-0.000615, 0.999405,-0.021804;;, + 31;4;-0.012616,-0.000551, 0.999502,-0.018246;;, + 32;4;-0.011095,-0.000484, 0.999597,-0.014795;;, + 33;4;-0.009555,-0.000417, 0.999685,-0.011553;;, + 34;4;-0.008021,-0.000350, 0.999765,-0.008607;;, + 35;4;-0.006517,-0.000285, 0.999835,-0.006030;;, + 36;4;-0.005062,-0.000221, 0.999894,-0.003876;;, + 37;4;-0.003674,-0.000160, 0.999941,-0.002181;;, + 38;4;-0.002362,-0.000103, 0.999974,-0.000967;;, + 39;4;-0.001136,-0.000050, 0.999994,-0.000240;;, + 40;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 41;4; 0.001136, 0.000050, 0.999993,-0.000240;;, + 42;4; 0.002362, 0.000103, 0.999974,-0.000967;;, + 43;4; 0.003674, 0.000160, 0.999941,-0.002181;;, + 44;4; 0.005062, 0.000221, 0.999894,-0.003876;;, + 45;4; 0.006517, 0.000285, 0.999835,-0.006030;;, + 46;4; 0.008021, 0.000350, 0.999765,-0.008607;;, + 47;4; 0.009555, 0.000417, 0.999685,-0.011553;;, + 48;4; 0.011095, 0.000484, 0.999596,-0.014795;;, + 49;4; 0.012616, 0.000551, 0.999502,-0.018246;;, + 50;4; 0.014088, 0.000615, 0.999405,-0.021804;;, + 51;4; 0.015484, 0.000676, 0.999308,-0.025363;;, + 52;4; 0.016778, 0.000733, 0.999214,-0.028814;;, + 53;4; 0.017947, 0.000784, 0.999126,-0.032056;;, + 54;4; 0.018975, 0.000828, 0.999045,-0.035002;;, + 55;4; 0.019848, 0.000867, 0.998975,-0.037578;;, + 56;4; 0.020560, 0.000898, 0.998916,-0.039733;;, + 57;4; 0.021108, 0.000922, 0.998870,-0.041427;;, + 58;4; 0.021494, 0.000938, 0.998837,-0.042642;;, + 59;4; 0.021720, 0.000948, 0.998817,-0.043369;;, + 60;4; 0.021794, 0.000952, 0.998811,-0.043609;;, + 61;4; 0.021681, 0.000947, 0.998817,-0.043383;;, + 62;4; 0.021364, 0.000933, 0.998834,-0.042748;;, + 63;4; 0.020870, 0.000911, 0.998861,-0.041759;;, + 64;4; 0.020221, 0.000883, 0.998896,-0.040461;;, + 65;4; 0.019436, 0.000849, 0.998939,-0.038890;;, + 66;4; 0.018529, 0.000809, 0.998989,-0.037076;;, + 67;4; 0.017514, 0.000765, 0.999044,-0.035045;;, + 68;4; 0.016402, 0.000716, 0.999105,-0.032820;;, + 69;4; 0.015204, 0.000664, 0.999170,-0.030422;;, + 70;4; 0.013928, 0.000608, 0.999240,-0.027869;;, + 71;4; 0.012583, 0.000549, 0.999313,-0.025178;;, + 72;4; 0.011179, 0.000488, 0.999390,-0.022368;;, + 73;4; 0.009723, 0.000425, 0.999469,-0.019456;;, + 74;4; 0.008227, 0.000359, 0.999551,-0.016461;;, + 75;4; 0.006701, 0.000293, 0.999634,-0.013408;;, + 76;4; 0.005161, 0.000225, 0.999718,-0.010327;;, + 77;4; 0.003631, 0.000159, 0.999802,-0.007266;;, + 78;4; 0.002152, 0.000094, 0.999883,-0.004305;;, + 79;4; 0.000815, 0.000036, 0.999956,-0.001631;;, + 80;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 81;4; 0.000000,-0.000000, 1.000000, 0.000000;;, + 82;4;-0.000815,-0.000036, 0.999956,-0.001631;;, + 83;4;-0.002152,-0.000094, 0.999883,-0.004305;;, + 84;4;-0.003631,-0.000159, 0.999802,-0.007266;;, + 85;4;-0.005161,-0.000225, 0.999718,-0.010327;;, + 86;4;-0.006701,-0.000293, 0.999634,-0.013408;;, + 87;4;-0.008226,-0.000359, 0.999551,-0.016461;;, + 88;4;-0.009723,-0.000425, 0.999469,-0.019456;;, + 89;4;-0.011179,-0.000488, 0.999390,-0.022368;;, + 90;4;-0.012583,-0.000549, 0.999313,-0.025178;;, + 91;4;-0.013928,-0.000608, 0.999240,-0.027869;;, + 92;4;-0.015204,-0.000664, 0.999170,-0.030422;;, + 93;4;-0.016402,-0.000716, 0.999105,-0.032820;;, + 94;4;-0.017514,-0.000765, 0.999044,-0.035045;;, + 95;4;-0.018529,-0.000809, 0.998989,-0.037076;;, + 96;4;-0.019436,-0.000849, 0.998939,-0.038890;;, + 97;4;-0.020221,-0.000883, 0.998896,-0.040461;;, + 98;4;-0.020870,-0.000911, 0.998861,-0.041759;;, + 99;4;-0.021364,-0.000933, 0.998834,-0.042748;;, + 100;4;-0.021681,-0.000947, 0.998817,-0.043383;;, + 101;4;-0.021794,-0.000952, 0.998811,-0.043609;;, + 102;4;-0.021720,-0.000948, 0.998817,-0.043369;;, + 103;4;-0.021494,-0.000938, 0.998837,-0.042642;;, + 104;4;-0.021108,-0.000922, 0.998870,-0.041427;;, + 105;4;-0.020560,-0.000898, 0.998916,-0.039733;;, + 106;4;-0.019848,-0.000867, 0.998975,-0.037578;;, + 107;4;-0.018975,-0.000828, 0.999045,-0.035002;;, + 108;4;-0.017947,-0.000784, 0.999126,-0.032056;;, + 109;4;-0.016778,-0.000733, 0.999214,-0.028814;;, + 110;4;-0.015484,-0.000676, 0.999308,-0.025363;;, + 111;4;-0.014088,-0.000615, 0.999405,-0.021804;;, + 112;4;-0.012616,-0.000551, 0.999502,-0.018246;;, + 113;4;-0.011095,-0.000484, 0.999597,-0.014795;;, + 114;4;-0.009555,-0.000417, 0.999685,-0.011553;;, + 115;4;-0.008021,-0.000350, 0.999765,-0.008607;;, + 116;4;-0.006517,-0.000285, 0.999835,-0.006030;;, + 117;4;-0.005062,-0.000221, 0.999894,-0.003876;;, + 118;4;-0.003674,-0.000160, 0.999941,-0.002181;;, + 119;4;-0.002362,-0.000103, 0.999974,-0.000967;;, + 120;4;-0.001136,-0.000050, 0.999994,-0.000240;;, + 121;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 122;4; 0.001136, 0.000050, 0.999993,-0.000240;;, + 123;4; 0.002362, 0.000103, 0.999974,-0.000967;;, + 124;4; 0.003674, 0.000160, 0.999941,-0.002181;;, + 125;4; 0.005062, 0.000221, 0.999894,-0.003876;;, + 126;4; 0.006517, 0.000285, 0.999835,-0.006030;;, + 127;4; 0.008021, 0.000350, 0.999765,-0.008607;;, + 128;4; 0.009555, 0.000417, 0.999685,-0.011553;;, + 129;4; 0.011095, 0.000484, 0.999596,-0.014795;;, + 130;4; 0.012616, 0.000551, 0.999502,-0.018246;;, + 131;4; 0.014088, 0.000615, 0.999405,-0.021804;;, + 132;4; 0.015484, 0.000676, 0.999308,-0.025363;;, + 133;4; 0.016778, 0.000733, 0.999214,-0.028814;;, + 134;4; 0.017947, 0.000784, 0.999126,-0.032056;;, + 135;4; 0.018975, 0.000828, 0.999045,-0.035002;;, + 136;4; 0.019848, 0.000867, 0.998975,-0.037578;;, + 137;4; 0.020560, 0.000898, 0.998916,-0.039733;;, + 138;4; 0.021109, 0.000922, 0.998870,-0.041427;;, + 139;4; 0.021494, 0.000938, 0.998837,-0.042642;;, + 140;4; 0.021720, 0.000948, 0.998817,-0.043369;;, + 141;4; 0.021794, 0.000952, 0.998811,-0.043609;;, + 142;4; 0.021681, 0.000947, 0.998817,-0.043383;;, + 143;4; 0.021364, 0.000933, 0.998834,-0.042748;;, + 144;4; 0.020870, 0.000911, 0.998861,-0.041759;;, + 145;4; 0.020221, 0.000883, 0.998896,-0.040461;;, + 146;4; 0.019436, 0.000849, 0.998939,-0.038890;;, + 147;4; 0.018529, 0.000809, 0.998989,-0.037076;;, + 148;4; 0.017514, 0.000765, 0.999044,-0.035045;;, + 149;4; 0.016402, 0.000716, 0.999105,-0.032820;;, + 150;4; 0.015204, 0.000664, 0.999170,-0.030422;;, + 151;4; 0.013928, 0.000608, 0.999240,-0.027869;;, + 152;4; 0.012583, 0.000549, 0.999313,-0.025178;;, + 153;4; 0.011179, 0.000488, 0.999390,-0.022368;;, + 154;4; 0.009723, 0.000425, 0.999469,-0.019456;;, + 155;4; 0.008227, 0.000359, 0.999551,-0.016461;;, + 156;4; 0.006701, 0.000293, 0.999634,-0.013408;;, + 157;4; 0.005161, 0.000225, 0.999718,-0.010327;;, + 158;4; 0.003631, 0.000159, 0.999802,-0.007266;;, + 159;4; 0.002152, 0.000094, 0.999883,-0.004305;;, + 160;4; 0.000815, 0.000036, 0.999956,-0.001631;;, + 161;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 162;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 163;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 164;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 165;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 166;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 167;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 168;4; 0.000000,-0.000000, 1.000000, 0.000000;;, + 169;4; 0.003877,-0.000000, 0.999915, 0.000000;;, + 170;4; 0.014799,-0.000000, 0.999677, 0.000000;;, + 171;4; 0.028821,-0.000000, 0.999371, 0.000000;;, + 172;4; 0.039742,-0.000000, 0.999133, 0.000000;;, + 173;4; 0.043619, 0.000000, 0.999048, 0.000000;;, + 174;4; 0.041150, 0.000000, 0.999133, 0.000000;;, + 175;4; 0.033580,-0.000000, 0.999371, 0.000000;;, + 176;4; 0.022207,-0.000000, 0.999677, 0.000000;;, + 177;4; 0.010132,-0.000000, 0.999915, 0.000000;;, + 178;4; 0.000000, 0.000000, 1.000000, 0.000000;;, + 179;4;-0.010132, 0.000000, 0.999915, 0.000000;;, + 180;4;-0.022206, 0.000000, 0.999677, 0.000000;;, + 181;4;-0.033580, 0.000000, 0.999371, 0.000000;;, + 182;4;-0.041150,-0.000000, 0.999133, 0.000000;;, + 183;4;-0.043619, 0.000000, 0.999048, 0.000000;;, + 184;4;-0.039742, 0.000000, 0.999133, 0.000000;;, + 185;4;-0.028821, 0.000000, 0.999371, 0.000000;;, + 186;4;-0.014798, 0.000000, 0.999677, 0.000000;;, + 187;4;-0.003877, 0.000000, 0.999915, 0.000000;;, + 188;4; 0.000000, 0.000000, 1.000000, 0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3; 0.000000, 6.750000, 0.000000;;, + 1;3;-0.000000, 6.750000, 0.000000;;, + 2;3; 0.000000, 6.750000, 0.000000;;, + 3;3; 0.000000, 6.750000, 0.000000;;, + 4;3; 0.000000, 6.750000, 0.000000;;, + 5;3; 0.000000, 6.750000, 0.000000;;, + 6;3; 0.000000, 6.750000, 0.000000;;, + 7;3; 0.000000, 6.750000,-0.000000;;, + 8;3; 0.000000, 6.750000,-0.000000;;, + 9;3; 0.000000, 6.750000, 0.000000;;, + 10;3; 0.000000, 6.750000,-0.000000;;, + 11;3; 0.000000, 6.750000, 0.000000;;, + 12;3; 0.000000, 6.750000, 0.000000;;, + 13;3; 0.000000, 6.750000, 0.000000;;, + 14;3; 0.000000, 6.750000,-0.000000;;, + 15;3; 0.000000, 6.750000,-0.000000;;, + 16;3; 0.000000, 6.750000, 0.000000;;, + 17;3;-0.000000, 6.750001,-0.000000;;, + 18;3; 0.000000, 6.750000, 0.000000;;, + 19;3; 0.000000, 6.750000, 0.000000;;, + 20;3; 0.000000, 6.750000, 0.000000;;, + 21;3; 0.000000, 6.750000, 0.000000;;, + 22;3; 0.000000, 6.750000, 0.000000;;, + 23;3;-0.000000, 6.750001,-0.000000;;, + 24;3; 0.000000, 6.750000, 0.000000;;, + 25;3; 0.000000, 6.750000, 0.000000;;, + 26;3; 0.000000, 6.750000,-0.000000;;, + 27;3; 0.000000, 6.750000, 0.000000;;, + 28;3; 0.000000, 6.750000, 0.000000;;, + 29;3; 0.000000, 6.750000, 0.000000;;, + 30;3; 0.000000, 6.750000, 0.000000;;, + 31;3; 0.000000, 6.750000, 0.000000;;, + 32;3; 0.000000, 6.750000,-0.000000;;, + 33;3; 0.000000, 6.750000,-0.000000;;, + 34;3; 0.000000, 6.750000, 0.000000;;, + 35;3; 0.000000, 6.750000, 0.000000;;, + 36;3; 0.000000, 6.750000,-0.000000;;, + 37;3; 0.000000, 6.750000, 0.000000;;, + 38;3; 0.000000, 6.750000, 0.000000;;, + 39;3;-0.000000, 6.750000, 0.000000;;, + 40;3; 0.000000, 6.750000, 0.000000;;, + 41;3;-0.000000, 6.750000, 0.000000;;, + 42;3; 0.000000, 6.750000, 0.000000;;, + 43;3; 0.000000, 6.750000, 0.000000;;, + 44;3; 0.000000, 6.750000, 0.000000;;, + 45;3; 0.000000, 6.750000, 0.000000;;, + 46;3; 0.000000, 6.750000,-0.000000;;, + 47;3; 0.000000, 6.750000, 0.000000;;, + 48;3; 0.000000, 6.750000, 0.000000;;, + 49;3; 0.000000, 6.750000, 0.000000;;, + 50;3; 0.000000, 6.750000,-0.000000;;, + 51;3; 0.000000, 6.750000, 0.000000;;, + 52;3; 0.000000, 6.750000, 0.000000;;, + 53;3; 0.000000, 6.750000, 0.000000;;, + 54;3; 0.000000, 6.750000, 0.000000;;, + 55;3; 0.000000, 6.750000,-0.000000;;, + 56;3; 0.000000, 6.750000, 0.000000;;, + 57;3;-0.000000, 6.750001,-0.000000;;, + 58;3; 0.000000, 6.750000, 0.000000;;, + 59;3; 0.000000, 6.750000, 0.000000;;, + 60;3; 0.000000, 6.750000, 0.000000;;, + 61;3; 0.000000, 6.750000, 0.000000;;, + 62;3; 0.000000, 6.750000, 0.000000;;, + 63;3; 0.000000, 6.750000,-0.000000;;, + 64;3; 0.000000, 6.750000, 0.000000;;, + 65;3; 0.000000, 6.750000, 0.000000;;, + 66;3; 0.000000, 6.750000, 0.000000;;, + 67;3; 0.000000, 6.750000, 0.000000;;, + 68;3; 0.000000, 6.750000, 0.000000;;, + 69;3; 0.000000, 6.750000,-0.000000;;, + 70;3; 0.000000, 6.750000,-0.000000;;, + 71;3; 0.000000, 6.750000,-0.000000;;, + 72;3; 0.000000, 6.750000,-0.000000;;, + 73;3; 0.000000, 6.749999, 0.000000;;, + 74;3; 0.000000, 6.750000, 0.000000;;, + 75;3; 0.000000, 6.750000, 0.000000;;, + 76;3;-0.000000, 6.750000,-0.000000;;, + 77;3; 0.000000, 6.750000, 0.000000;;, + 78;3; 0.000000, 6.750000,-0.000000;;, + 79;3; 0.000000, 6.750000, 0.000000;;, + 80;3; 0.000000, 6.750000, 0.000000;;, + 81;3; 0.000000, 6.750000,-0.000000;;, + 82;3; 0.000000, 6.750000, 0.000000;;, + 83;3; 0.000000, 6.750000,-0.000000;;, + 84;3; 0.000000, 6.750000, 0.000000;;, + 85;3;-0.000000, 6.750000,-0.000000;;, + 86;3; 0.000000, 6.750000, 0.000000;;, + 87;3; 0.000000, 6.750000,-0.000000;;, + 88;3; 0.000000, 6.750000, 0.000000;;, + 89;3; 0.000000, 6.750000,-0.000000;;, + 90;3; 0.000000, 6.750000,-0.000000;;, + 91;3; 0.000000, 6.750000, 0.000000;;, + 92;3; 0.000000, 6.750000,-0.000000;;, + 93;3; 0.000000, 6.750000,-0.000000;;, + 94;3; 0.000000, 6.750000,-0.000000;;, + 95;3; 0.000000, 6.750000, 0.000000;;, + 96;3; 0.000000, 6.750000,-0.000000;;, + 97;3; 0.000000, 6.750000, 0.000000;;, + 98;3; 0.000000, 6.750000, 0.000000;;, + 99;3; 0.000000, 6.750000,-0.000000;;, + 100;3; 0.000000, 6.750000, 0.000000;;, + 101;3; 0.000000, 6.750000, 0.000000;;, + 102;3; 0.000000, 6.750000,-0.000000;;, + 103;3; 0.000000, 6.750000, 0.000000;;, + 104;3;-0.000000, 6.750000, 0.000000;;, + 105;3; 0.000000, 6.750000, 0.000000;;, + 106;3; 0.000000, 6.750000, 0.000000;;, + 107;3; 0.000000, 6.750000,-0.000000;;, + 108;3; 0.000000, 6.750000, 0.000000;;, + 109;3; 0.000000, 6.750000, 0.000000;;, + 110;3; 0.000000, 6.750000,-0.000000;;, + 111;3; 0.000000, 6.750000,-0.000000;;, + 112;3; 0.000000, 6.750000,-0.000000;;, + 113;3; 0.000000, 6.750000,-0.000000;;, + 114;3; 0.000000, 6.750000, 0.000000;;, + 115;3; 0.000000, 6.750000, 0.000000;;, + 116;3; 0.000000, 6.750000, 0.000000;;, + 117;3; 0.000000, 6.750000,-0.000000;;, + 118;3; 0.000000, 6.750000,-0.000000;;, + 119;3; 0.000000, 6.750000,-0.000000;;, + 120;3;-0.000000, 6.750000, 0.000000;;, + 121;3; 0.000000, 6.750000,-0.000000;;, + 122;3;-0.000000, 6.750000,-0.000000;;, + 123;3; 0.000000, 6.750000,-0.000000;;, + 124;3; 0.000000, 6.750000, 0.000000;;, + 125;3; 0.000000, 6.750000,-0.000000;;, + 126;3; 0.000000, 6.750000, 0.000000;;, + 127;3; 0.000000, 6.750000,-0.000000;;, + 128;3; 0.000000, 6.750000, 0.000000;;, + 129;3; 0.000000, 6.750000,-0.000000;;, + 130;3; 0.000000, 6.750000,-0.000000;;, + 131;3; 0.000000, 6.750000,-0.000000;;, + 132;3; 0.000000, 6.750000,-0.000000;;, + 133;3; 0.000000, 6.750000, 0.000000;;, + 134;3; 0.000000, 6.750000,-0.000000;;, + 135;3; 0.000000, 6.750000, 0.000000;;, + 136;3; 0.000000, 6.750000, 0.000000;;, + 137;3; 0.000000, 6.750000, 0.000000;;, + 138;3;-0.000000, 6.750000, 0.000000;;, + 139;3; 0.000000, 6.750000,-0.000000;;, + 140;3; 0.000000, 6.750000,-0.000000;;, + 141;3; 0.000000, 6.750000, 0.000000;;, + 142;3; 0.000000, 6.750000, 0.000000;;, + 143;3; 0.000000, 6.750000,-0.000000;;, + 144;3; 0.000000, 6.750000, 0.000000;;, + 145;3; 0.000000, 6.750000, 0.000000;;, + 146;3; 0.000000, 6.750000, 0.000000;;, + 147;3; 0.000000, 6.750000,-0.000000;;, + 148;3; 0.000000, 6.750000, 0.000000;;, + 149;3; 0.000000, 6.750000, 0.000000;;, + 150;3; 0.000000, 6.750000,-0.000000;;, + 151;3; 0.000000, 6.750000,-0.000000;;, + 152;3; 0.000000, 6.750000,-0.000000;;, + 153;3; 0.000000, 6.750000,-0.000000;;, + 154;3; 0.000000, 6.750000,-0.000000;;, + 155;3; 0.000000, 6.750000,-0.000000;;, + 156;3; 0.000000, 6.750000,-0.000000;;, + 157;3;-0.000000, 6.750000, 0.000000;;, + 158;3; 0.000000, 6.750000, 0.000000;;, + 159;3; 0.000000, 6.750000,-0.000000;;, + 160;3; 0.000000, 6.750000, 0.000000;;, + 161;3; 0.000000, 6.750000,-0.000000;;, + 162;3; 0.000000, 6.750000, 0.000000;;, + 163;3; 0.000000, 6.750000, 0.000000;;, + 164;3; 0.000000, 6.750000, 0.000000;;, + 165;3; 0.000000, 6.750000, 0.000000;;, + 166;3; 0.000000, 6.750000, 0.000000;;, + 167;3; 0.000000, 6.750000, 0.000000;;, + 168;3; 0.000000, 6.750000, 0.000000;;, + 169;3; 0.000000, 6.750000, 0.000000;;, + 170;3; 0.000000, 6.750000, 0.000000;;, + 171;3; 0.000000, 6.750000, 0.000000;;, + 172;3; 0.000000, 6.750000, 0.000000;;, + 173;3; 0.000000, 6.750000, 0.000000;;, + 174;3; 0.000000, 6.750000, 0.000000;;, + 175;3; 0.000000, 6.750000, 0.000000;;, + 176;3; 0.000000, 6.750000, 0.000000;;, + 177;3; 0.000000, 6.750000, 0.000000;;, + 178;3; 0.000000, 6.750000, 0.000000;;, + 179;3; 0.000000, 6.750000, 0.000000;;, + 180;3; 0.000000, 6.750000, 0.000000;;, + 181;3; 0.000000, 6.750000, 0.000000;;, + 182;3; 0.000000, 6.750000, 0.000000;;, + 183;3; 0.000000, 6.750000, 0.000000;;, + 184;3; 0.000000, 6.750000, 0.000000;;, + 185;3; 0.000000, 6.750000, 0.000000;;, + 186;3; 0.000000, 6.750000, 0.000000;;, + 187;3; 0.000000, 6.750000, 0.000000;;, + 188;3; 0.000000, 6.750000, 0.000000;;; + } + } + Animation { + {Armature_Arm_Left} + AnimationKey { // Rotation + 0; + 189; + 0;4; 0.648448, 0.757709,-0.045973,-0.057269;;, + 1;4; 0.648161, 0.757936,-0.045920,-0.057331;;, + 2;4; 0.647294, 0.758622,-0.045761,-0.057521;;, + 3;4; 0.645844, 0.759770,-0.045495,-0.057837;;, + 4;4; 0.643821, 0.761372,-0.045124,-0.058279;;, + 5;4; 0.641250, 0.763407,-0.044653,-0.058841;;, + 6;4; 0.638175, 0.765842,-0.044088,-0.059513;;, + 7;4; 0.634660, 0.768625,-0.043443,-0.060281;;, + 8;4; 0.630790, 0.771689,-0.042734,-0.061126;;, + 9;4; 0.626671, 0.774950,-0.041978,-0.062026;;, + 10;4; 0.622424, 0.778313,-0.041199,-0.062953;;, + 11;4; 0.618177, 0.781676,-0.040419,-0.063881;;, + 12;4; 0.614058, 0.784937,-0.039664,-0.064781;;, + 13;4; 0.610189, 0.788000,-0.038954,-0.065626;;, + 14;4; 0.606673, 0.790784,-0.038309,-0.066394;;, + 15;4; 0.603598, 0.793218,-0.037745,-0.067066;;, + 16;4; 0.601027, 0.795254,-0.037273,-0.067628;;, + 17;4; 0.599004, 0.796856,-0.036902,-0.068069;;, + 18;4; 0.597555, 0.798003,-0.036636,-0.068386;;, + 19;4; 0.596688, 0.798690,-0.036477,-0.068576;;, + 20;4; 0.596401, 0.798917,-0.036424,-0.068638;;, + 21;4; 0.596760, 0.798627,-0.036471,-0.068580;;, + 22;4; 0.597846, 0.797750,-0.036614,-0.068404;;, + 23;4; 0.599661, 0.796284,-0.036852,-0.068109;;, + 24;4; 0.602194, 0.794238,-0.037184,-0.067698;;, + 25;4; 0.605413, 0.791638,-0.037606,-0.067176;;, + 26;4; 0.609264, 0.788527,-0.038110,-0.066551;;, + 27;4; 0.613666, 0.784972,-0.038687,-0.065837;;, + 28;4; 0.618511, 0.781058,-0.039322,-0.065050;;, + 29;4; 0.623668, 0.776892,-0.039998,-0.064213;;, + 30;4; 0.628987, 0.772597,-0.040695,-0.063350;;, + 31;4; 0.634305, 0.768301,-0.041393,-0.062487;;, + 32;4; 0.639462, 0.764135,-0.042069,-0.061650;;, + 33;4; 0.644308, 0.760222,-0.042704,-0.060864;;, + 34;4; 0.648710, 0.756666,-0.043281,-0.060150;;, + 35;4; 0.652560, 0.753556,-0.043785,-0.059525;;, + 36;4; 0.655780, 0.750956,-0.044207,-0.059002;;, + 37;4; 0.658313, 0.748910,-0.044539,-0.058591;;, + 38;4; 0.660128, 0.747444,-0.044777,-0.058297;;, + 39;4; 0.661214, 0.746567,-0.044920,-0.058121;;, + 40;4; 0.661573, 0.746277,-0.044967,-0.058062;;, + 41;4; 0.661328, 0.746479,-0.044910,-0.058126;;, + 42;4; 0.660587, 0.747091,-0.044737,-0.058317;;, + 43;4; 0.659348, 0.748115,-0.044449,-0.058638;;, + 44;4; 0.657620, 0.749544,-0.044046,-0.059085;;, + 45;4; 0.655424, 0.751359,-0.043535,-0.059653;;, + 46;4; 0.652797, 0.753531,-0.042924,-0.060333;;, + 47;4; 0.649794, 0.756013,-0.042224,-0.061110;;, + 48;4; 0.646488, 0.758746,-0.041455,-0.061966;;, + 49;4; 0.642969, 0.761655,-0.040636,-0.062876;;, + 50;4; 0.639341, 0.764654,-0.039791,-0.063815;;, + 51;4; 0.635713, 0.767653,-0.038946,-0.064754;;, + 52;4; 0.632194, 0.770562,-0.038127,-0.065665;;, + 53;4; 0.628889, 0.773294,-0.037357,-0.066520;;, + 54;4; 0.625885, 0.775777,-0.036658,-0.067297;;, + 55;4; 0.623258, 0.777949,-0.036047,-0.067977;;, + 56;4; 0.621062, 0.779764,-0.035535,-0.068545;;, + 57;4; 0.619334, 0.781193,-0.035133,-0.068993;;, + 58;4; 0.618095, 0.782216,-0.034845,-0.069313;;, + 59;4; 0.617355, 0.782829,-0.034672,-0.069505;;, + 60;4; 0.617110, 0.783031,-0.034615,-0.069568;;, + 61;4; 0.617174, 0.782991,-0.034614,-0.069562;;, + 62;4; 0.617353, 0.782876,-0.034615,-0.069541;;, + 63;4; 0.617631, 0.782698,-0.034624,-0.069502;;, + 64;4; 0.617995, 0.782463,-0.034645,-0.069440;;, + 65;4; 0.618435, 0.782178,-0.034685,-0.069353;;, + 66;4; 0.618940, 0.781848,-0.034749,-0.069236;;, + 67;4; 0.619505, 0.781478,-0.034841,-0.069085;;, + 68;4; 0.620120, 0.781070,-0.034969,-0.068894;;, + 69;4; 0.620781, 0.780629,-0.035139,-0.068658;;, + 70;4; 0.621482, 0.780157,-0.035359,-0.068369;;, + 71;4; 0.622217, 0.779656,-0.035640,-0.068019;;, + 72;4; 0.622979, 0.779130,-0.035993,-0.067597;;, + 73;4; 0.623764, 0.778580,-0.036434,-0.067088;;, + 74;4; 0.624563, 0.778009,-0.036984,-0.066473;;, + 75;4; 0.625368, 0.777419,-0.037673,-0.065726;;, + 76;4; 0.626168, 0.776813,-0.038544,-0.064805;;, + 77;4; 0.626943, 0.776195,-0.039669,-0.063644;;, + 78;4; 0.627662, 0.775573,-0.041178,-0.062123;;, + 79;4; 0.628249, 0.774961,-0.043370,-0.059964;;, + 80;4; 0.628391, 0.774424,-0.047456,-0.056046;;, + 81;4; 0.000990, 0.997299,-0.072151,-0.013690;;, + 82;4;-0.011967, 0.997270,-0.071970,-0.015145;;, + 83;4;-0.018796, 0.997206,-0.071870,-0.016486;;, + 84;4;-0.023483, 0.997134,-0.071799,-0.017763;;, + 85;4;-0.026976, 0.997057,-0.071745,-0.018986;;, + 86;4;-0.029682, 0.996980,-0.071701,-0.020158;;, + 87;4;-0.031824, 0.996902,-0.071665,-0.021280;;, + 88;4;-0.033538, 0.996826,-0.071634,-0.022353;;, + 89;4;-0.034915, 0.996751,-0.071609,-0.023375;;, + 90;4;-0.036019, 0.996679,-0.071588,-0.024345;;, + 91;4;-0.036900, 0.996610,-0.071570,-0.025261;;, + 92;4;-0.037594, 0.996544,-0.071555,-0.026120;;, + 93;4;-0.038132, 0.996482,-0.071542,-0.026918;;, + 94;4;-0.038539, 0.996425,-0.071531,-0.027653;;, + 95;4;-0.038836, 0.996372,-0.071523,-0.028317;;, + 96;4;-0.039042, 0.996325,-0.071516,-0.028907;;, + 97;4;-0.039174, 0.996284,-0.071511,-0.029414;;, + 98;4;-0.039248, 0.996250,-0.071507,-0.029831;;, + 99;4;-0.039280, 0.996225,-0.071504,-0.030146;;, + 100;4;-0.039287, 0.996208,-0.071503,-0.030348;;, + 101;4;-0.039284, 0.996202,-0.071502,-0.030419;;, + 102;4;-0.039062, 0.996208,-0.071506,-0.030327;;, + 103;4;-0.038392, 0.996227,-0.071517,-0.030048;;, + 104;4;-0.037270, 0.996257,-0.071535,-0.029583;;, + 105;4;-0.035704, 0.996300,-0.071560,-0.028932;;, + 106;4;-0.033715, 0.996354,-0.071592,-0.028106;;, + 107;4;-0.031335, 0.996419,-0.071630,-0.027118;;, + 108;4;-0.028615, 0.996493,-0.071674,-0.025988;;, + 109;4;-0.025621, 0.996574,-0.071723,-0.024744;;, + 110;4;-0.022434, 0.996661,-0.071774,-0.023420;;, + 111;4;-0.019147, 0.996751,-0.071827,-0.022055;;, + 112;4;-0.015860, 0.996840,-0.071880,-0.020690;;, + 113;4;-0.012673, 0.996927,-0.071931,-0.019366;;, + 114;4;-0.009679, 0.997009,-0.071979,-0.018122;;, + 115;4;-0.006959, 0.997083,-0.072023,-0.016992;;, + 116;4;-0.004579, 0.997148,-0.072062,-0.016004;;, + 117;4;-0.002590, 0.997202,-0.072094,-0.015177;;, + 118;4;-0.001024, 0.997244,-0.072119,-0.014527;;, + 119;4; 0.000098, 0.997275,-0.072137,-0.014061;;, + 120;4; 0.000769, 0.997293,-0.072148,-0.013782;;, + 121;4; 0.000990, 0.997299,-0.072151,-0.013690;;, + 122;4; 0.000769, 0.997293,-0.072148,-0.013782;;, + 123;4; 0.000098, 0.997275,-0.072137,-0.014061;;, + 124;4;-0.001024, 0.997244,-0.072119,-0.014527;;, + 125;4;-0.002590, 0.997202,-0.072094,-0.015177;;, + 126;4;-0.004579, 0.997148,-0.072062,-0.016004;;, + 127;4;-0.006959, 0.997083,-0.072023,-0.016992;;, + 128;4;-0.009679, 0.997009,-0.071979,-0.018122;;, + 129;4;-0.012673, 0.996927,-0.071931,-0.019366;;, + 130;4;-0.015860, 0.996840,-0.071880,-0.020690;;, + 131;4;-0.019147, 0.996751,-0.071827,-0.022055;;, + 132;4;-0.022434, 0.996661,-0.071774,-0.023420;;, + 133;4;-0.025621, 0.996574,-0.071723,-0.024744;;, + 134;4;-0.028615, 0.996493,-0.071674,-0.025988;;, + 135;4;-0.031335, 0.996419,-0.071630,-0.027118;;, + 136;4;-0.033715, 0.996354,-0.071592,-0.028106;;, + 137;4;-0.035704, 0.996300,-0.071560,-0.028932;;, + 138;4;-0.037270, 0.996257,-0.071535,-0.029583;;, + 139;4;-0.038392, 0.996227,-0.071517,-0.030048;;, + 140;4;-0.039062, 0.996208,-0.071506,-0.030327;;, + 141;4;-0.039284, 0.996202,-0.071502,-0.030419;;, + 142;4;-0.039115, 0.996208,-0.071505,-0.030336;;, + 143;4;-0.038639, 0.996224,-0.071513,-0.030100;;, + 144;4;-0.037892, 0.996249,-0.071526,-0.029733;;, + 145;4;-0.036906, 0.996282,-0.071542,-0.029250;;, + 146;4;-0.035703, 0.996322,-0.071562,-0.028665;;, + 147;4;-0.034305, 0.996368,-0.071585,-0.027989;;, + 148;4;-0.032728, 0.996419,-0.071611,-0.027232;;, + 149;4;-0.030984, 0.996475,-0.071640,-0.026401;;, + 150;4;-0.029084, 0.996536,-0.071671,-0.025504;;, + 151;4;-0.027040, 0.996601,-0.071705,-0.024547;;, + 152;4;-0.024856, 0.996669,-0.071741,-0.023537;;, + 153;4;-0.022540, 0.996740,-0.071779,-0.022479;;, + 154;4;-0.020096, 0.996813,-0.071819,-0.021379;;, + 155;4;-0.017525, 0.996888,-0.071861,-0.020245;;, + 156;4;-0.014829, 0.996965,-0.071905,-0.019082;;, + 157;4;-0.012005, 0.997043,-0.071950,-0.017902;;, + 158;4;-0.009047, 0.997120,-0.071997,-0.016718;;, + 159;4;-0.005937, 0.997194,-0.072047,-0.015555;;, + 160;4;-0.002640, 0.997260,-0.072098,-0.014470;;, + 161;4; 0.000990, 0.997299,-0.072151,-0.013690;;, + 162;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 163;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 164;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 165;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 166;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 167;4; 0.003930, 0.958043,-0.286296,-0.013151;;, + 168;4; 0.648448, 0.757709,-0.045973,-0.057269;;, + 169;4; 0.654493, 0.752186,-0.040667,-0.064731;;, + 170;4; 0.658020, 0.748822,-0.037013,-0.069986;;, + 171;4; 0.659629, 0.747251,-0.035126,-0.072743;;, + 172;4; 0.660600, 0.746345,-0.034493,-0.073596;;, + 173;4; 0.662067, 0.745032,-0.034351,-0.073580;;, + 174;4; 0.664030, 0.743414,-0.034783,-0.072577;;, + 175;4; 0.665879, 0.742098,-0.036358,-0.069861;;, + 176;4; 0.667289, 0.741198,-0.038892,-0.065911;;, + 177;4; 0.668012, 0.740701,-0.041785,-0.061811;;, + 178;4; 0.668060, 0.740475,-0.044458,-0.058453;;, + 179;4; 0.667246, 0.740936,-0.047522,-0.055224;;, + 180;4; 0.665271, 0.742616,-0.051527,-0.051513;;, + 181;4; 0.662480, 0.745165,-0.055526,-0.048126;;, + 182;4; 0.659627, 0.747806,-0.058315,-0.045969;;, + 183;4; 0.657320, 0.749902,-0.059309,-0.045384;;, + 184;4; 0.655964, 0.751255,-0.058163,-0.046490;;, + 185;4; 0.655437, 0.752065,-0.054765,-0.049326;;, + 186;4; 0.654752, 0.752963,-0.050391,-0.052966;;, + 187;4; 0.652660, 0.754722,-0.047040,-0.055932;;, + 188;4; 0.648448, 0.757709,-0.045973,-0.057269;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3;-2.000000, 6.750000, 0.000000;;, + 1;3;-2.000000, 6.750000, 0.000000;;, + 2;3;-2.000000, 6.750000, 0.000000;;, + 3;3;-2.000000, 6.750000, 0.000000;;, + 4;3;-2.000000, 6.750000, 0.000000;;, + 5;3;-2.000000, 6.750000, 0.000000;;, + 6;3;-2.000000, 6.750000, 0.000000;;, + 7;3;-2.000000, 6.750000,-0.000000;;, + 8;3;-2.000000, 6.750000,-0.000000;;, + 9;3;-2.000000, 6.750000, 0.000000;;, + 10;3;-2.000000, 6.750000,-0.000000;;, + 11;3;-2.000000, 6.750000, 0.000000;;, + 12;3;-2.000000, 6.750000, 0.000000;;, + 13;3;-2.000000, 6.750000, 0.000000;;, + 14;3;-2.000000, 6.750000,-0.000000;;, + 15;3;-2.000000, 6.750000,-0.000000;;, + 16;3;-2.000000, 6.750000, 0.000000;;, + 17;3;-2.000000, 6.750001,-0.000000;;, + 18;3;-2.000000, 6.750000, 0.000000;;, + 19;3;-2.000000, 6.750000, 0.000000;;, + 20;3;-2.000000, 6.750000, 0.000000;;, + 21;3;-2.000000, 6.750000, 0.000000;;, + 22;3;-2.000000, 6.750000, 0.000000;;, + 23;3;-2.000000, 6.750001,-0.000000;;, + 24;3;-2.000000, 6.750000, 0.000000;;, + 25;3;-2.000000, 6.750000, 0.000000;;, + 26;3;-2.000000, 6.750000,-0.000000;;, + 27;3;-2.000000, 6.750000, 0.000000;;, + 28;3;-2.000000, 6.750000, 0.000000;;, + 29;3;-2.000000, 6.750000, 0.000000;;, + 30;3;-2.000000, 6.750000, 0.000000;;, + 31;3;-2.000000, 6.750000, 0.000000;;, + 32;3;-2.000000, 6.750000,-0.000000;;, + 33;3;-2.000000, 6.750000,-0.000000;;, + 34;3;-2.000000, 6.750000, 0.000000;;, + 35;3;-2.000000, 6.750000, 0.000000;;, + 36;3;-2.000000, 6.750000,-0.000000;;, + 37;3;-2.000000, 6.750000, 0.000000;;, + 38;3;-2.000000, 6.750000, 0.000000;;, + 39;3;-2.000000, 6.750000, 0.000000;;, + 40;3;-2.000000, 6.750000, 0.000000;;, + 41;3;-2.000000, 6.750000, 0.000000;;, + 42;3;-2.000000, 6.750000, 0.000000;;, + 43;3;-2.000000, 6.750000, 0.000000;;, + 44;3;-2.000000, 6.750000, 0.000000;;, + 45;3;-2.000000, 6.750000, 0.000000;;, + 46;3;-2.000000, 6.750000,-0.000000;;, + 47;3;-2.000000, 6.750000, 0.000000;;, + 48;3;-2.000000, 6.750000, 0.000000;;, + 49;3;-2.000000, 6.750000, 0.000000;;, + 50;3;-2.000000, 6.750000,-0.000000;;, + 51;3;-2.000000, 6.750000, 0.000000;;, + 52;3;-2.000000, 6.750000, 0.000000;;, + 53;3;-2.000000, 6.750000, 0.000000;;, + 54;3;-2.000000, 6.750000, 0.000000;;, + 55;3;-2.000000, 6.750000,-0.000000;;, + 56;3;-2.000000, 6.750000, 0.000000;;, + 57;3;-2.000000, 6.750001,-0.000000;;, + 58;3;-2.000000, 6.750000, 0.000000;;, + 59;3;-2.000000, 6.750000, 0.000000;;, + 60;3;-2.000000, 6.750000, 0.000000;;, + 61;3;-2.000000, 6.750000, 0.000000;;, + 62;3;-2.000000, 6.750000, 0.000000;;, + 63;3;-2.000000, 6.750000,-0.000000;;, + 64;3;-2.000000, 6.750000, 0.000000;;, + 65;3;-2.000000, 6.750000, 0.000000;;, + 66;3;-2.000000, 6.750000, 0.000000;;, + 67;3;-2.000000, 6.750000, 0.000000;;, + 68;3;-2.000000, 6.750000, 0.000000;;, + 69;3;-2.000000, 6.750000,-0.000000;;, + 70;3;-2.000000, 6.750000,-0.000000;;, + 71;3;-2.000000, 6.750000,-0.000000;;, + 72;3;-2.000000, 6.750000,-0.000000;;, + 73;3;-2.000000, 6.749999, 0.000000;;, + 74;3;-2.000000, 6.750000, 0.000000;;, + 75;3;-2.000000, 6.750000, 0.000000;;, + 76;3;-2.000000, 6.750000,-0.000000;;, + 77;3;-2.000000, 6.750000, 0.000000;;, + 78;3;-2.000000, 6.750000,-0.000000;;, + 79;3;-2.000000, 6.750000, 0.000000;;, + 80;3;-2.000000, 6.750000, 0.000000;;, + 81;3;-2.000000, 6.750000,-0.000000;;, + 82;3;-2.000000, 6.750000, 0.000000;;, + 83;3;-2.000000, 6.750000,-0.000000;;, + 84;3;-2.000000, 6.750000, 0.000000;;, + 85;3;-2.000000, 6.750000,-0.000000;;, + 86;3;-2.000000, 6.750000, 0.000000;;, + 87;3;-2.000000, 6.750000,-0.000000;;, + 88;3;-2.000000, 6.750000, 0.000000;;, + 89;3;-2.000000, 6.750000,-0.000000;;, + 90;3;-2.000000, 6.750000,-0.000000;;, + 91;3;-2.000000, 6.750000, 0.000000;;, + 92;3;-2.000000, 6.750000,-0.000000;;, + 93;3;-2.000000, 6.750000,-0.000000;;, + 94;3;-2.000000, 6.750000,-0.000000;;, + 95;3;-2.000000, 6.750000, 0.000000;;, + 96;3;-2.000000, 6.750000,-0.000000;;, + 97;3;-2.000000, 6.750000, 0.000000;;, + 98;3;-2.000000, 6.750000, 0.000000;;, + 99;3;-2.000000, 6.750000,-0.000000;;, + 100;3;-2.000000, 6.750000, 0.000000;;, + 101;3;-2.000000, 6.750000, 0.000000;;, + 102;3;-2.000000, 6.750000,-0.000000;;, + 103;3;-2.000000, 6.750000, 0.000000;;, + 104;3;-2.000000, 6.750000, 0.000000;;, + 105;3;-2.000000, 6.750000, 0.000000;;, + 106;3;-2.000000, 6.750000, 0.000000;;, + 107;3;-2.000000, 6.750000,-0.000000;;, + 108;3;-2.000000, 6.750000, 0.000000;;, + 109;3;-2.000000, 6.750000, 0.000000;;, + 110;3;-2.000000, 6.750000,-0.000000;;, + 111;3;-2.000000, 6.750000,-0.000000;;, + 112;3;-2.000000, 6.750000,-0.000000;;, + 113;3;-2.000000, 6.750000,-0.000000;;, + 114;3;-2.000000, 6.750000, 0.000000;;, + 115;3;-2.000000, 6.750000, 0.000000;;, + 116;3;-2.000000, 6.750000, 0.000000;;, + 117;3;-2.000000, 6.750000,-0.000000;;, + 118;3;-2.000000, 6.750000,-0.000000;;, + 119;3;-2.000000, 6.750000,-0.000000;;, + 120;3;-2.000000, 6.750000, 0.000000;;, + 121;3;-2.000000, 6.750000,-0.000000;;, + 122;3;-2.000000, 6.750000,-0.000000;;, + 123;3;-2.000000, 6.750000,-0.000000;;, + 124;3;-2.000000, 6.750000, 0.000000;;, + 125;3;-2.000000, 6.750000,-0.000000;;, + 126;3;-2.000000, 6.750000, 0.000000;;, + 127;3;-2.000000, 6.750000,-0.000000;;, + 128;3;-2.000000, 6.750000, 0.000000;;, + 129;3;-2.000000, 6.750000,-0.000000;;, + 130;3;-2.000000, 6.750000,-0.000000;;, + 131;3;-2.000000, 6.750000,-0.000000;;, + 132;3;-2.000000, 6.750000,-0.000000;;, + 133;3;-2.000000, 6.750000, 0.000000;;, + 134;3;-2.000000, 6.750000,-0.000000;;, + 135;3;-2.000000, 6.750000, 0.000000;;, + 136;3;-2.000000, 6.750000, 0.000000;;, + 137;3;-2.000000, 6.750000, 0.000000;;, + 138;3;-2.000000, 6.750000, 0.000000;;, + 139;3;-2.000000, 6.750000,-0.000000;;, + 140;3;-2.000000, 6.750000,-0.000000;;, + 141;3;-2.000000, 6.750000, 0.000000;;, + 142;3;-2.000000, 6.750000, 0.000000;;, + 143;3;-2.000000, 6.750000,-0.000000;;, + 144;3;-2.000000, 6.750000, 0.000000;;, + 145;3;-2.000000, 6.750000, 0.000000;;, + 146;3;-2.000000, 6.750000, 0.000000;;, + 147;3;-2.000000, 6.750000,-0.000000;;, + 148;3;-2.000000, 6.750000, 0.000000;;, + 149;3;-2.000000, 6.750000, 0.000000;;, + 150;3;-2.000000, 6.750000,-0.000000;;, + 151;3;-2.000000, 6.750000,-0.000000;;, + 152;3;-2.000000, 6.750000,-0.000000;;, + 153;3;-2.000000, 6.750000,-0.000000;;, + 154;3;-2.000000, 6.750000,-0.000000;;, + 155;3;-2.000000, 6.750000,-0.000000;;, + 156;3;-2.000000, 6.750000,-0.000000;;, + 157;3;-2.000000, 6.750000, 0.000000;;, + 158;3;-2.000000, 6.750000, 0.000000;;, + 159;3;-2.000000, 6.750000,-0.000000;;, + 160;3;-2.000000, 6.750000, 0.000000;;, + 161;3;-2.000000, 6.750000,-0.000000;;, + 162;3;-2.000000, 6.750000, 0.000000;;, + 163;3;-2.000000, 6.750000, 0.000000;;, + 164;3;-2.000000, 6.750000, 0.000000;;, + 165;3;-2.000000, 6.750000, 0.000000;;, + 166;3;-2.000000, 6.750000, 0.000000;;, + 167;3;-2.000000, 6.750000, 0.000000;;, + 168;3;-2.000000, 6.750000, 0.000000;;, + 169;3;-2.000000, 6.750000, 0.000000;;, + 170;3;-2.000000, 6.750000, 0.000000;;, + 171;3;-2.000000, 6.750000, 0.000000;;, + 172;3;-2.000000, 6.750000, 0.000000;;, + 173;3;-2.000000, 6.750000, 0.000000;;, + 174;3;-2.000000, 6.750000, 0.000000;;, + 175;3;-2.000000, 6.750000, 0.000000;;, + 176;3;-2.000000, 6.750000, 0.000000;;, + 177;3;-2.000000, 6.750000, 0.000000;;, + 178;3;-2.000000, 6.750000, 0.000000;;, + 179;3;-2.000000, 6.750000, 0.000000;;, + 180;3;-2.000000, 6.750000, 0.000000;;, + 181;3;-2.000000, 6.750000, 0.000000;;, + 182;3;-2.000000, 6.750000, 0.000000;;, + 183;3;-2.000000, 6.750000, 0.000000;;, + 184;3;-2.000000, 6.750000, 0.000000;;, + 185;3;-2.000000, 6.750000, 0.000000;;, + 186;3;-2.000000, 6.750000, 0.000000;;, + 187;3;-2.000000, 6.750000, 0.000000;;, + 188;3;-2.000000, 6.750000, 0.000000;;; + } + } + Animation { + {Armature_Arm_Right} + AnimationKey { // Rotation + 0; + 189; + 0;4; 0.648448, 0.757709, 0.045973, 0.057269;;, + 1;4; 0.648161, 0.757936, 0.045920, 0.057331;;, + 2;4; 0.647294, 0.758622, 0.045761, 0.057521;;, + 3;4; 0.645844, 0.759770, 0.045495, 0.057837;;, + 4;4; 0.643821, 0.761372, 0.045124, 0.058279;;, + 5;4; 0.641250, 0.763407, 0.044653, 0.058841;;, + 6;4; 0.638175, 0.765842, 0.044088, 0.059513;;, + 7;4; 0.634660, 0.768625, 0.043443, 0.060281;;, + 8;4; 0.630790, 0.771689, 0.042734, 0.061126;;, + 9;4; 0.626671, 0.774950, 0.041978, 0.062026;;, + 10;4; 0.622424, 0.778313, 0.041199, 0.062953;;, + 11;4; 0.618177, 0.781676, 0.040419, 0.063881;;, + 12;4; 0.614058, 0.784937, 0.039664, 0.064781;;, + 13;4; 0.610189, 0.788000, 0.038954, 0.065626;;, + 14;4; 0.606673, 0.790784, 0.038309, 0.066394;;, + 15;4; 0.603598, 0.793218, 0.037745, 0.067066;;, + 16;4; 0.601027, 0.795254, 0.037273, 0.067628;;, + 17;4; 0.599004, 0.796856, 0.036902, 0.068069;;, + 18;4; 0.597555, 0.798003, 0.036636, 0.068386;;, + 19;4; 0.596688, 0.798690, 0.036477, 0.068576;;, + 20;4; 0.596401, 0.798917, 0.036424, 0.068638;;, + 21;4; 0.596760, 0.798627, 0.036471, 0.068580;;, + 22;4; 0.597846, 0.797750, 0.036614, 0.068404;;, + 23;4; 0.599661, 0.796284, 0.036852, 0.068109;;, + 24;4; 0.602194, 0.794238, 0.037184, 0.067698;;, + 25;4; 0.605413, 0.791638, 0.037606, 0.067176;;, + 26;4; 0.609264, 0.788527, 0.038110, 0.066551;;, + 27;4; 0.613666, 0.784972, 0.038687, 0.065837;;, + 28;4; 0.618511, 0.781058, 0.039322, 0.065050;;, + 29;4; 0.623668, 0.776892, 0.039998, 0.064213;;, + 30;4; 0.628987, 0.772597, 0.040695, 0.063350;;, + 31;4; 0.634305, 0.768301, 0.041393, 0.062487;;, + 32;4; 0.639462, 0.764135, 0.042069, 0.061650;;, + 33;4; 0.644308, 0.760222, 0.042704, 0.060864;;, + 34;4; 0.648710, 0.756666, 0.043281, 0.060150;;, + 35;4; 0.652560, 0.753556, 0.043785, 0.059525;;, + 36;4; 0.655780, 0.750956, 0.044207, 0.059002;;, + 37;4; 0.658313, 0.748910, 0.044539, 0.058591;;, + 38;4; 0.660128, 0.747444, 0.044777, 0.058297;;, + 39;4; 0.661214, 0.746567, 0.044920, 0.058121;;, + 40;4; 0.661573, 0.746277, 0.044967, 0.058062;;, + 41;4; 0.661328, 0.746479, 0.044910, 0.058126;;, + 42;4; 0.660587, 0.747091, 0.044737, 0.058317;;, + 43;4; 0.659348, 0.748115, 0.044449, 0.058638;;, + 44;4; 0.657620, 0.749544, 0.044046, 0.059085;;, + 45;4; 0.655424, 0.751359, 0.043535, 0.059653;;, + 46;4; 0.652797, 0.753531, 0.042924, 0.060333;;, + 47;4; 0.649794, 0.756013, 0.042224, 0.061110;;, + 48;4; 0.646488, 0.758746, 0.041455, 0.061966;;, + 49;4; 0.642969, 0.761655, 0.040636, 0.062876;;, + 50;4; 0.639341, 0.764654, 0.039791, 0.063815;;, + 51;4; 0.635713, 0.767653, 0.038946, 0.064754;;, + 52;4; 0.632194, 0.770562, 0.038127, 0.065665;;, + 53;4; 0.628889, 0.773294, 0.037357, 0.066520;;, + 54;4; 0.625885, 0.775777, 0.036658, 0.067297;;, + 55;4; 0.623258, 0.777949, 0.036047, 0.067977;;, + 56;4; 0.621062, 0.779764, 0.035535, 0.068545;;, + 57;4; 0.619334, 0.781193, 0.035133, 0.068993;;, + 58;4; 0.618095, 0.782216, 0.034845, 0.069313;;, + 59;4; 0.617355, 0.782829, 0.034672, 0.069505;;, + 60;4; 0.617110, 0.783031, 0.034615, 0.069568;;, + 61;4; 0.617174, 0.782991, 0.034614, 0.069562;;, + 62;4; 0.617353, 0.782876, 0.034615, 0.069541;;, + 63;4; 0.617631, 0.782698, 0.034624, 0.069502;;, + 64;4; 0.617995, 0.782463, 0.034645, 0.069440;;, + 65;4; 0.618435, 0.782178, 0.034685, 0.069353;;, + 66;4; 0.618940, 0.781848, 0.034749, 0.069236;;, + 67;4; 0.619505, 0.781478, 0.034841, 0.069085;;, + 68;4; 0.620120, 0.781070, 0.034969, 0.068894;;, + 69;4; 0.620781, 0.780629, 0.035139, 0.068658;;, + 70;4; 0.621482, 0.780157, 0.035359, 0.068369;;, + 71;4; 0.622217, 0.779656, 0.035640, 0.068019;;, + 72;4; 0.622979, 0.779130, 0.035993, 0.067597;;, + 73;4; 0.623764, 0.778580, 0.036434, 0.067088;;, + 74;4; 0.624563, 0.778009, 0.036984, 0.066473;;, + 75;4; 0.625368, 0.777419, 0.037673, 0.065726;;, + 76;4; 0.626168, 0.776813, 0.038544, 0.064805;;, + 77;4; 0.626943, 0.776195, 0.039669, 0.063644;;, + 78;4; 0.627662, 0.775573, 0.041178, 0.062123;;, + 79;4; 0.628249, 0.774961, 0.043370, 0.059964;;, + 80;4; 0.628391, 0.774424, 0.047456, 0.056046;;, + 81;4; 0.000990, 0.997299, 0.072151, 0.013690;;, + 82;4;-0.011967, 0.997270, 0.071970, 0.015145;;, + 83;4;-0.018796, 0.997206, 0.071870, 0.016486;;, + 84;4;-0.023483, 0.997134, 0.071799, 0.017763;;, + 85;4;-0.026976, 0.997057, 0.071745, 0.018986;;, + 86;4;-0.029682, 0.996980, 0.071701, 0.020158;;, + 87;4;-0.031824, 0.996902, 0.071665, 0.021280;;, + 88;4;-0.033538, 0.996826, 0.071634, 0.022353;;, + 89;4;-0.034915, 0.996751, 0.071609, 0.023375;;, + 90;4;-0.036019, 0.996679, 0.071588, 0.024345;;, + 91;4;-0.036900, 0.996610, 0.071570, 0.025261;;, + 92;4;-0.037594, 0.996544, 0.071555, 0.026120;;, + 93;4;-0.038132, 0.996482, 0.071542, 0.026918;;, + 94;4;-0.038539, 0.996425, 0.071531, 0.027653;;, + 95;4;-0.038836, 0.996372, 0.071523, 0.028317;;, + 96;4;-0.039042, 0.996325, 0.071516, 0.028907;;, + 97;4;-0.039174, 0.996284, 0.071511, 0.029414;;, + 98;4;-0.039248, 0.996250, 0.071507, 0.029831;;, + 99;4;-0.039280, 0.996225, 0.071504, 0.030146;;, + 100;4;-0.039287, 0.996208, 0.071503, 0.030348;;, + 101;4;-0.039284, 0.996202, 0.071502, 0.030419;;, + 102;4;-0.039062, 0.996208, 0.071506, 0.030327;;, + 103;4;-0.038392, 0.996227, 0.071517, 0.030048;;, + 104;4;-0.037270, 0.996257, 0.071535, 0.029583;;, + 105;4;-0.035704, 0.996300, 0.071560, 0.028932;;, + 106;4;-0.033715, 0.996354, 0.071592, 0.028106;;, + 107;4;-0.031335, 0.996419, 0.071630, 0.027118;;, + 108;4;-0.028615, 0.996493, 0.071674, 0.025988;;, + 109;4;-0.025621, 0.996574, 0.071723, 0.024744;;, + 110;4;-0.022434, 0.996661, 0.071774, 0.023420;;, + 111;4;-0.019147, 0.996751, 0.071827, 0.022055;;, + 112;4;-0.015860, 0.996840, 0.071880, 0.020690;;, + 113;4;-0.012673, 0.996927, 0.071931, 0.019366;;, + 114;4;-0.009679, 0.997009, 0.071979, 0.018122;;, + 115;4;-0.006959, 0.997083, 0.072023, 0.016992;;, + 116;4;-0.004579, 0.997148, 0.072062, 0.016004;;, + 117;4;-0.002590, 0.997202, 0.072094, 0.015177;;, + 118;4;-0.001024, 0.997244, 0.072119, 0.014527;;, + 119;4; 0.000098, 0.997275, 0.072137, 0.014061;;, + 120;4; 0.000769, 0.997293, 0.072148, 0.013782;;, + 121;4; 0.000990, 0.997299, 0.072151, 0.013690;;, + 122;4; 0.000769, 0.997293, 0.072148, 0.013782;;, + 123;4; 0.000098, 0.997275, 0.072137, 0.014061;;, + 124;4;-0.001024, 0.997244, 0.072119, 0.014527;;, + 125;4;-0.002590, 0.997202, 0.072094, 0.015177;;, + 126;4;-0.004579, 0.997148, 0.072062, 0.016004;;, + 127;4;-0.006959, 0.997083, 0.072023, 0.016992;;, + 128;4;-0.009679, 0.997009, 0.071979, 0.018122;;, + 129;4;-0.012673, 0.996927, 0.071931, 0.019366;;, + 130;4;-0.015860, 0.996840, 0.071880, 0.020690;;, + 131;4;-0.019147, 0.996751, 0.071827, 0.022055;;, + 132;4;-0.022434, 0.996661, 0.071774, 0.023420;;, + 133;4;-0.025621, 0.996574, 0.071723, 0.024744;;, + 134;4;-0.028615, 0.996493, 0.071674, 0.025988;;, + 135;4;-0.031335, 0.996419, 0.071630, 0.027118;;, + 136;4;-0.033715, 0.996354, 0.071592, 0.028106;;, + 137;4;-0.035704, 0.996300, 0.071560, 0.028932;;, + 138;4;-0.037270, 0.996257, 0.071535, 0.029583;;, + 139;4;-0.038392, 0.996227, 0.071517, 0.030048;;, + 140;4;-0.039062, 0.996208, 0.071506, 0.030327;;, + 141;4;-0.039284, 0.996202, 0.071502, 0.030419;;, + 142;4;-0.039115, 0.996208, 0.071505, 0.030336;;, + 143;4;-0.038639, 0.996224, 0.071513, 0.030100;;, + 144;4;-0.037892, 0.996249, 0.071526, 0.029733;;, + 145;4;-0.036906, 0.996282, 0.071542, 0.029250;;, + 146;4;-0.035703, 0.996322, 0.071562, 0.028665;;, + 147;4;-0.034305, 0.996368, 0.071585, 0.027989;;, + 148;4;-0.032728, 0.996419, 0.071611, 0.027232;;, + 149;4;-0.030984, 0.996475, 0.071640, 0.026401;;, + 150;4;-0.029084, 0.996536, 0.071671, 0.025504;;, + 151;4;-0.027040, 0.996601, 0.071705, 0.024547;;, + 152;4;-0.024856, 0.996669, 0.071741, 0.023537;;, + 153;4;-0.022540, 0.996740, 0.071779, 0.022479;;, + 154;4;-0.020096, 0.996813, 0.071819, 0.021379;;, + 155;4;-0.017525, 0.996888, 0.071861, 0.020245;;, + 156;4;-0.014829, 0.996965, 0.071905, 0.019082;;, + 157;4;-0.012005, 0.997043, 0.071950, 0.017902;;, + 158;4;-0.009047, 0.997120, 0.071997, 0.016718;;, + 159;4;-0.005937, 0.997194, 0.072047, 0.015555;;, + 160;4;-0.002640, 0.997260, 0.072098, 0.014470;;, + 161;4; 0.000990, 0.997299, 0.072151, 0.013690;;, + 162;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 163;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 164;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 165;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 166;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 167;4; 0.003930, 0.958043, 0.286296, 0.013151;;, + 168;4; 0.648448, 0.757709, 0.045973, 0.057269;;, + 169;4; 0.649549, 0.757271, 0.047200, 0.056091;;, + 170;4; 0.649725, 0.756946, 0.050660, 0.053001;;, + 171;4; 0.649483, 0.756671, 0.055081, 0.049073;;, + 172;4; 0.649550, 0.756346, 0.058515, 0.045995;;, + 173;4; 0.650401, 0.755911, 0.059724, 0.044837;;, + 174;4; 0.652287, 0.754678, 0.058785, 0.045494;;, + 175;4; 0.655167, 0.752148, 0.056006, 0.047730;;, + 176;4; 0.658293, 0.749160, 0.051993, 0.051173;;, + 177;4; 0.660622, 0.746956, 0.047989, 0.054888;;, + 178;4; 0.661573, 0.746277, 0.044967, 0.058062;;, + 179;4; 0.660467, 0.747385, 0.042436, 0.061362;;, + 180;4; 0.656915, 0.750262, 0.039819, 0.065439;;, + 181;4; 0.652243, 0.753921, 0.037593, 0.069365;;, + 182;4; 0.648570, 0.756808, 0.036216, 0.072016;;, + 183;4; 0.647260, 0.757932, 0.035794, 0.072889;;, + 184;4; 0.647163, 0.758022, 0.036704, 0.071517;;, + 185;4; 0.646979, 0.757987, 0.039247, 0.067643;;, + 186;4; 0.646980, 0.757869, 0.042510, 0.062649;;, + 187;4; 0.647442, 0.757754, 0.045057, 0.058724;;, + 188;4; 0.648448, 0.757709, 0.045973, 0.057269;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3; 2.000000, 6.750000, 0.000000;;, + 1;3; 2.000000, 6.750000, 0.000000;;, + 2;3; 2.000000, 6.750000, 0.000000;;, + 3;3; 2.000000, 6.750000, 0.000000;;, + 4;3; 2.000000, 6.750000, 0.000000;;, + 5;3; 2.000000, 6.750000, 0.000000;;, + 6;3; 2.000000, 6.750000, 0.000000;;, + 7;3; 2.000000, 6.750000,-0.000000;;, + 8;3; 2.000000, 6.750000,-0.000000;;, + 9;3; 2.000000, 6.750000, 0.000000;;, + 10;3; 2.000000, 6.750000,-0.000000;;, + 11;3; 2.000000, 6.750000, 0.000000;;, + 12;3; 2.000000, 6.750000, 0.000000;;, + 13;3; 2.000000, 6.750000, 0.000000;;, + 14;3; 2.000000, 6.750000,-0.000000;;, + 15;3; 2.000000, 6.750000,-0.000000;;, + 16;3; 2.000000, 6.750000, 0.000000;;, + 17;3; 2.000000, 6.750001,-0.000000;;, + 18;3; 2.000000, 6.750000, 0.000000;;, + 19;3; 2.000000, 6.750000, 0.000000;;, + 20;3; 2.000000, 6.750000, 0.000000;;, + 21;3; 2.000000, 6.750000, 0.000000;;, + 22;3; 2.000000, 6.750000, 0.000000;;, + 23;3; 2.000000, 6.750001,-0.000000;;, + 24;3; 2.000000, 6.750000, 0.000000;;, + 25;3; 2.000000, 6.750000, 0.000000;;, + 26;3; 2.000000, 6.750000,-0.000000;;, + 27;3; 2.000000, 6.750000, 0.000000;;, + 28;3; 2.000000, 6.750000, 0.000000;;, + 29;3; 2.000000, 6.750000, 0.000000;;, + 30;3; 2.000000, 6.750000, 0.000000;;, + 31;3; 2.000000, 6.750000, 0.000000;;, + 32;3; 2.000000, 6.750000,-0.000000;;, + 33;3; 2.000000, 6.750000,-0.000000;;, + 34;3; 2.000000, 6.750000, 0.000000;;, + 35;3; 2.000000, 6.750000, 0.000000;;, + 36;3; 2.000000, 6.750000,-0.000000;;, + 37;3; 2.000000, 6.750000, 0.000000;;, + 38;3; 2.000000, 6.750000, 0.000000;;, + 39;3; 2.000000, 6.750000, 0.000000;;, + 40;3; 2.000000, 6.750000, 0.000000;;, + 41;3; 2.000000, 6.750000, 0.000000;;, + 42;3; 2.000000, 6.750000, 0.000000;;, + 43;3; 2.000000, 6.750000, 0.000000;;, + 44;3; 2.000000, 6.750000, 0.000000;;, + 45;3; 2.000000, 6.750000, 0.000000;;, + 46;3; 2.000000, 6.750000,-0.000000;;, + 47;3; 2.000000, 6.750000, 0.000000;;, + 48;3; 2.000000, 6.750000, 0.000000;;, + 49;3; 2.000000, 6.750000, 0.000000;;, + 50;3; 2.000000, 6.750000,-0.000000;;, + 51;3; 2.000000, 6.750000, 0.000000;;, + 52;3; 2.000000, 6.750000, 0.000000;;, + 53;3; 2.000000, 6.750000, 0.000000;;, + 54;3; 2.000000, 6.750000, 0.000000;;, + 55;3; 2.000000, 6.750000,-0.000000;;, + 56;3; 2.000000, 6.750000, 0.000000;;, + 57;3; 2.000000, 6.750001,-0.000000;;, + 58;3; 2.000000, 6.750000, 0.000000;;, + 59;3; 2.000000, 6.750000, 0.000000;;, + 60;3; 2.000000, 6.750000, 0.000000;;, + 61;3; 2.000000, 6.750000, 0.000000;;, + 62;3; 2.000000, 6.750000, 0.000000;;, + 63;3; 2.000000, 6.750000,-0.000000;;, + 64;3; 2.000000, 6.750000, 0.000000;;, + 65;3; 2.000000, 6.750000, 0.000000;;, + 66;3; 2.000000, 6.750000, 0.000000;;, + 67;3; 2.000000, 6.750000, 0.000000;;, + 68;3; 2.000000, 6.750000, 0.000000;;, + 69;3; 2.000000, 6.750000,-0.000000;;, + 70;3; 2.000000, 6.750000,-0.000000;;, + 71;3; 2.000000, 6.750000,-0.000000;;, + 72;3; 2.000000, 6.750000,-0.000000;;, + 73;3; 2.000000, 6.749999, 0.000000;;, + 74;3; 2.000000, 6.750000, 0.000000;;, + 75;3; 2.000000, 6.750000, 0.000000;;, + 76;3; 2.000000, 6.750000,-0.000000;;, + 77;3; 2.000000, 6.750000, 0.000000;;, + 78;3; 2.000000, 6.750000,-0.000000;;, + 79;3; 2.000000, 6.750000, 0.000000;;, + 80;3; 2.000000, 6.750000, 0.000000;;, + 81;3; 2.000000, 6.750000,-0.000000;;, + 82;3; 2.000000, 6.750000, 0.000000;;, + 83;3; 2.000000, 6.750000,-0.000000;;, + 84;3; 2.000000, 6.750000, 0.000000;;, + 85;3; 2.000000, 6.750000,-0.000000;;, + 86;3; 2.000000, 6.750000, 0.000000;;, + 87;3; 2.000000, 6.750000,-0.000000;;, + 88;3; 2.000000, 6.750000, 0.000000;;, + 89;3; 2.000000, 6.750000,-0.000000;;, + 90;3; 2.000000, 6.750000,-0.000000;;, + 91;3; 2.000000, 6.750000, 0.000000;;, + 92;3; 2.000000, 6.750000,-0.000000;;, + 93;3; 2.000000, 6.750000,-0.000000;;, + 94;3; 2.000000, 6.750000,-0.000000;;, + 95;3; 2.000000, 6.750000, 0.000000;;, + 96;3; 2.000000, 6.750000,-0.000000;;, + 97;3; 2.000000, 6.750000, 0.000000;;, + 98;3; 2.000000, 6.750000, 0.000000;;, + 99;3; 2.000000, 6.750000,-0.000000;;, + 100;3; 2.000000, 6.750000, 0.000000;;, + 101;3; 2.000000, 6.750000, 0.000000;;, + 102;3; 2.000000, 6.750000,-0.000000;;, + 103;3; 2.000000, 6.750000, 0.000000;;, + 104;3; 2.000000, 6.750000, 0.000000;;, + 105;3; 2.000000, 6.750000, 0.000000;;, + 106;3; 2.000000, 6.750000, 0.000000;;, + 107;3; 2.000000, 6.750000,-0.000000;;, + 108;3; 2.000000, 6.750000, 0.000000;;, + 109;3; 2.000000, 6.750000, 0.000000;;, + 110;3; 2.000000, 6.750000,-0.000000;;, + 111;3; 2.000000, 6.750000,-0.000000;;, + 112;3; 2.000000, 6.750000,-0.000000;;, + 113;3; 2.000000, 6.750000,-0.000000;;, + 114;3; 2.000000, 6.750000, 0.000000;;, + 115;3; 2.000000, 6.750000, 0.000000;;, + 116;3; 2.000000, 6.750000, 0.000000;;, + 117;3; 2.000000, 6.750000,-0.000000;;, + 118;3; 2.000000, 6.750000,-0.000000;;, + 119;3; 2.000000, 6.750000,-0.000000;;, + 120;3; 2.000000, 6.750000, 0.000000;;, + 121;3; 2.000000, 6.750000,-0.000000;;, + 122;3; 2.000000, 6.750000,-0.000000;;, + 123;3; 2.000000, 6.750000,-0.000000;;, + 124;3; 2.000000, 6.750000, 0.000000;;, + 125;3; 2.000000, 6.750000,-0.000000;;, + 126;3; 2.000000, 6.750000, 0.000000;;, + 127;3; 2.000000, 6.750000,-0.000000;;, + 128;3; 2.000000, 6.750000, 0.000000;;, + 129;3; 2.000000, 6.750000,-0.000000;;, + 130;3; 2.000000, 6.750000,-0.000000;;, + 131;3; 2.000000, 6.750000,-0.000000;;, + 132;3; 2.000000, 6.750000,-0.000000;;, + 133;3; 2.000000, 6.750000, 0.000000;;, + 134;3; 2.000000, 6.750000,-0.000000;;, + 135;3; 2.000000, 6.750000, 0.000000;;, + 136;3; 2.000000, 6.750000, 0.000000;;, + 137;3; 2.000000, 6.750000, 0.000000;;, + 138;3; 2.000000, 6.750000, 0.000000;;, + 139;3; 2.000000, 6.750000,-0.000000;;, + 140;3; 2.000000, 6.750000,-0.000000;;, + 141;3; 2.000000, 6.750000, 0.000000;;, + 142;3; 2.000000, 6.750000, 0.000000;;, + 143;3; 2.000000, 6.750000,-0.000000;;, + 144;3; 2.000000, 6.750000, 0.000000;;, + 145;3; 2.000000, 6.750000, 0.000000;;, + 146;3; 2.000000, 6.750000, 0.000000;;, + 147;3; 2.000000, 6.750000,-0.000000;;, + 148;3; 2.000000, 6.750000, 0.000000;;, + 149;3; 2.000000, 6.750000, 0.000000;;, + 150;3; 2.000000, 6.750000,-0.000000;;, + 151;3; 2.000000, 6.750000,-0.000000;;, + 152;3; 2.000000, 6.750000,-0.000000;;, + 153;3; 2.000000, 6.750000,-0.000000;;, + 154;3; 2.000000, 6.750000,-0.000000;;, + 155;3; 2.000000, 6.750000,-0.000000;;, + 156;3; 2.000000, 6.750000,-0.000000;;, + 157;3; 2.000000, 6.750000, 0.000000;;, + 158;3; 2.000000, 6.750000, 0.000000;;, + 159;3; 2.000000, 6.750000,-0.000000;;, + 160;3; 2.000000, 6.750000, 0.000000;;, + 161;3; 2.000000, 6.750000,-0.000000;;, + 162;3; 2.000000, 6.750000, 0.000000;;, + 163;3; 2.000000, 6.750000, 0.000000;;, + 164;3; 2.000000, 6.750000, 0.000000;;, + 165;3; 2.000000, 6.750000, 0.000000;;, + 166;3; 2.000000, 6.750000, 0.000000;;, + 167;3; 2.000000, 6.750000, 0.000000;;, + 168;3; 2.000000, 6.750000, 0.000000;;, + 169;3; 2.000000, 6.750000, 0.000000;;, + 170;3; 2.000000, 6.750000, 0.000000;;, + 171;3; 2.000000, 6.750000, 0.000000;;, + 172;3; 2.000000, 6.750000, 0.000000;;, + 173;3; 2.000000, 6.750000, 0.000000;;, + 174;3; 2.000000, 6.750000, 0.000000;;, + 175;3; 2.000000, 6.750000, 0.000000;;, + 176;3; 2.000000, 6.750000, 0.000000;;, + 177;3; 2.000000, 6.750000, 0.000000;;, + 178;3; 2.000000, 6.750000, 0.000000;;, + 179;3; 2.000000, 6.750000, 0.000000;;, + 180;3; 2.000000, 6.750000, 0.000000;;, + 181;3; 2.000000, 6.750000, 0.000000;;, + 182;3; 2.000000, 6.750000, 0.000000;;, + 183;3; 2.000000, 6.750000, 0.000000;;, + 184;3; 2.000000, 6.750000, 0.000000;;, + 185;3; 2.000000, 6.750000, 0.000000;;, + 186;3; 2.000000, 6.750000, 0.000000;;, + 187;3; 2.000000, 6.750000, 0.000000;;, + 188;3; 2.000000, 6.750000, 0.000000;;; + } + } + Animation { + {Armature_Leg_Right} + AnimationKey { // Rotation + 0; + 189; + 0;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 1;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 2;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 3;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 4;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 5;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 6;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 7;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 8;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 9;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 10;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 11;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 12;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 13;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 14;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 15;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 16;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 17;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 18;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 19;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 20;4;-0.043619, 0.999048,-0.000000,-0.000000;;, + 21;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 22;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 23;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 24;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 25;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 26;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 27;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 28;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 29;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 30;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 31;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 32;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 33;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 34;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 35;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 36;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 37;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 38;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 39;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 40;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 41;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 42;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 43;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 44;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 45;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 46;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 47;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 48;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 49;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 50;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 51;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 52;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 53;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 54;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 55;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 56;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 57;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 58;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 59;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 60;4;-0.043619, 0.999048,-0.000000,-0.000000;;, + 61;4;-0.043616, 0.999053,-0.000000,-0.000000;;, + 62;4;-0.043594, 0.999067,-0.000000,-0.000000;;, + 63;4;-0.043536, 0.999089,-0.000000,-0.000000;;, + 64;4;-0.043427, 0.999117,-0.000000,-0.000000;;, + 65;4;-0.043249, 0.999151,-0.000000,-0.000000;;, + 66;4;-0.042989, 0.999191,-0.000000,-0.000000;;, + 67;4;-0.042626, 0.999235,-0.000000,-0.000000;;, + 68;4;-0.042144, 0.999283,-0.000000,-0.000000;;, + 69;4;-0.041519, 0.999336,-0.000000,-0.000000;;, + 70;4;-0.040725, 0.999391,-0.000000,-0.000000;;, + 71;4;-0.039732, 0.999450,-0.000000,-0.000000;;, + 72;4;-0.038501, 0.999511,-0.000000,-0.000000;;, + 73;4;-0.036980, 0.999575,-0.000000,-0.000000;;, + 74;4;-0.035101, 0.999640,-0.000000,-0.000000;;, + 75;4;-0.032769, 0.999707,-0.000000,-0.000000;;, + 76;4;-0.029842, 0.999774,-0.000000,-0.000000;;, + 77;4;-0.026086, 0.999841,-0.000000,-0.000000;;, + 78;4;-0.021070, 0.999906,-0.000000,-0.000000;;, + 79;4;-0.013794, 0.999964,-0.000000,-0.000000;;, + 80;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 81;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 82;4; 0.705874, 0.708245, 0.000000,-0.000000;;, + 83;4; 0.703907, 0.710101, 0.000000,-0.000000;;, + 84;4; 0.701752, 0.712152, 0.000000,-0.000000;;, + 85;4; 0.699534, 0.714271, 0.000000,-0.000000;;, + 86;4; 0.697308, 0.716402, 0.000000,-0.000000;;, + 87;4; 0.695107, 0.718513, 0.000000,-0.000000;;, + 88;4; 0.692952, 0.720584, 0.000000,-0.000000;;, + 89;4; 0.690857, 0.722597, 0.000000,-0.000000;;, + 90;4; 0.688837, 0.724539, 0.000000,-0.000000;;, + 91;4; 0.686904, 0.726399, 0.000000,-0.000000;;, + 92;4; 0.685070, 0.728163, 0.000000,-0.000000;;, + 93;4; 0.683348, 0.729820, 0.000000,-0.000000;;, + 94;4; 0.681750, 0.731358, 0.000000,-0.000000;;, + 95;4; 0.680291, 0.732761, 0.000000,-0.000000;;, + 96;4; 0.678987, 0.734015, 0.000000,-0.000000;;, + 97;4; 0.677857, 0.735101, 0.000000,-0.000000;;, + 98;4; 0.676923, 0.735998, 0.000000,-0.000000;;, + 99;4; 0.676211, 0.736682, 0.000000,-0.000000;;, + 100;4; 0.675754, 0.737121, 0.000000,-0.000000;;, + 101;4; 0.675590, 0.737277, 0.000000,-0.000000;;, + 102;4; 0.675764, 0.737111, 0.000000,-0.000000;;, + 103;4; 0.676289, 0.736609, 0.000000,-0.000000;;, + 104;4; 0.677167, 0.735768, 0.000000,-0.000000;;, + 105;4; 0.678392, 0.734595, 0.000000,-0.000000;;, + 106;4; 0.679949, 0.733105, 0.000000,-0.000000;;, + 107;4; 0.681811, 0.731323, 0.000000,-0.000000;;, + 108;4; 0.683940, 0.729285, 0.000000,-0.000000;;, + 109;4; 0.686283, 0.727042, 0.000000,-0.000000;;, + 110;4; 0.688777, 0.724654, 0.000000,-0.000000;;, + 111;4; 0.691349, 0.722192, 0.000000,-0.000000;;, + 112;4; 0.693920, 0.719730, 0.000000,-0.000000;;, + 113;4; 0.696415, 0.717342, 0.000000,-0.000000;;, + 114;4; 0.698758, 0.715099, 0.000000,-0.000000;;, + 115;4; 0.700886, 0.713062, 0.000000,-0.000000;;, + 116;4; 0.702749, 0.711279, 0.000000,-0.000000;;, + 117;4; 0.704305, 0.709789, 0.000000,-0.000000;;, + 118;4; 0.705530, 0.708616, 0.000000,-0.000000;;, + 119;4; 0.706408, 0.707776, 0.000000,-0.000000;;, + 120;4; 0.706933, 0.707273, 0.000000,-0.000000;;, + 121;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 122;4; 0.706933, 0.707273, 0.000000,-0.000000;;, + 123;4; 0.706408, 0.707776, 0.000000,-0.000000;;, + 124;4; 0.705530, 0.708616, 0.000000,-0.000000;;, + 125;4; 0.704305, 0.709789, 0.000000,-0.000000;;, + 126;4; 0.702749, 0.711279, 0.000000,-0.000000;;, + 127;4; 0.700886, 0.713062, 0.000000,-0.000000;;, + 128;4; 0.698758, 0.715099, 0.000000,-0.000000;;, + 129;4; 0.696415, 0.717342, 0.000000,-0.000000;;, + 130;4; 0.693920, 0.719730, 0.000000,-0.000000;;, + 131;4; 0.691349, 0.722192, 0.000000,-0.000000;;, + 132;4; 0.688777, 0.724654, 0.000000,-0.000000;;, + 133;4; 0.686283, 0.727042, 0.000000,-0.000000;;, + 134;4; 0.683940, 0.729285, 0.000000,-0.000000;;, + 135;4; 0.681811, 0.731323, 0.000000,-0.000000;;, + 136;4; 0.679949, 0.733105, 0.000000,-0.000000;;, + 137;4; 0.678392, 0.734596, 0.000000,-0.000000;;, + 138;4; 0.677167, 0.735768, 0.000000,-0.000000;;, + 139;4; 0.676289, 0.736609, 0.000000,-0.000000;;, + 140;4; 0.675764, 0.737111, 0.000000,-0.000000;;, + 141;4; 0.675590, 0.737277, 0.000000,-0.000000;;, + 142;4; 0.675754, 0.737121, 0.000000,-0.000000;;, + 143;4; 0.676211, 0.736682, 0.000000,-0.000000;;, + 144;4; 0.676923, 0.735998, 0.000000,-0.000000;;, + 145;4; 0.677857, 0.735101, 0.000000,-0.000000;;, + 146;4; 0.678987, 0.734015, 0.000000,-0.000000;;, + 147;4; 0.680291, 0.732761, 0.000000,-0.000000;;, + 148;4; 0.681750, 0.731357, 0.000000,-0.000000;;, + 149;4; 0.683348, 0.729820, 0.000000,-0.000000;;, + 150;4; 0.685070, 0.728162, 0.000000,-0.000000;;, + 151;4; 0.686904, 0.726398, 0.000000,-0.000000;;, + 152;4; 0.688837, 0.724539, 0.000000,-0.000000;;, + 153;4; 0.690857, 0.722596, 0.000000,-0.000000;;, + 154;4; 0.692952, 0.720583, 0.000000,-0.000000;;, + 155;4; 0.695107, 0.718512, 0.000000,-0.000000;;, + 156;4; 0.697308, 0.716401, 0.000000,-0.000000;;, + 157;4; 0.699534, 0.714270, 0.000000,-0.000000;;, + 158;4; 0.701752, 0.712151, 0.000000,-0.000000;;, + 159;4; 0.703907, 0.710100, 0.000000,-0.000000;;, + 160;4; 0.705874, 0.708244, 0.000000,-0.000000;;, + 161;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 162;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 163;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 164;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 165;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 166;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 167;4; 0.000000, 0.991445, 0.130526,-0.000000;;, + 168;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 169;4; 0.034052, 0.993234, 0.000000,-0.000000;;, + 170;4; 0.129904, 0.974175, 0.000000,-0.000000;;, + 171;4; 0.252901, 0.949704, 0.000000,-0.000000;;, + 172;4; 0.348675, 0.930646, 0.000000,-0.000000;;, + 173;4; 0.382684, 0.923880, 0.000000,-0.000000;;, + 174;4; 0.361005, 0.930646, 0.000000,-0.000000;;, + 175;4; 0.294618, 0.949704, 0.000000,-0.000000;;, + 176;4; 0.194899, 0.974175, 0.000000,-0.000000;;, + 177;4; 0.088939, 0.993234, 0.000000,-0.000000;;, + 178;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 179;4;-0.088939, 0.993234,-0.000000,-0.000000;;, + 180;4;-0.194899, 0.974175,-0.000000,-0.000000;;, + 181;4;-0.294618, 0.949704,-0.000000,-0.000000;;, + 182;4;-0.361005, 0.930646,-0.000000,-0.000000;;, + 183;4;-0.382683, 0.923880,-0.000000,-0.000000;;, + 184;4;-0.348675, 0.930646,-0.000000,-0.000000;;, + 185;4;-0.252901, 0.949704,-0.000000,-0.000000;;, + 186;4;-0.129903, 0.974175,-0.000000,-0.000000;;, + 187;4;-0.034052, 0.993234,-0.000000,-0.000000;;, + 188;4; 0.000000, 1.000000,-0.000000,-0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 0.999999;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 0.999999;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 0.999999;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3; 1.000000, 0.000000,-0.000001;;, + 1;3; 1.000000,-0.000000,-0.000001;;, + 2;3; 1.000000,-0.000000,-0.000001;;, + 3;3; 1.000000,-0.000000,-0.000001;;, + 4;3; 1.000000,-0.000000,-0.000001;;, + 5;3; 1.000000,-0.000000,-0.000001;;, + 6;3; 1.000000,-0.000000,-0.000001;;, + 7;3; 1.000000,-0.000000,-0.000001;;, + 8;3; 1.000000,-0.000000,-0.000001;;, + 9;3; 1.000000,-0.000000,-0.000001;;, + 10;3; 1.000000,-0.000000,-0.000000;;, + 11;3; 1.000000,-0.000000,-0.000000;;, + 12;3; 1.000000,-0.000000,-0.000000;;, + 13;3; 1.000000,-0.000000,-0.000000;;, + 14;3; 1.000000,-0.000000,-0.000000;;, + 15;3; 1.000000,-0.000000,-0.000001;;, + 16;3; 1.000000,-0.000000,-0.000001;;, + 17;3; 1.000000,-0.000000,-0.000001;;, + 18;3; 1.000000,-0.000000,-0.000001;;, + 19;3; 1.000000,-0.000000,-0.000001;;, + 20;3; 1.000000,-0.000000,-0.000001;;, + 21;3; 1.000000,-0.000000,-0.000001;;, + 22;3; 1.000000,-0.000000,-0.000000;;, + 23;3; 1.000000,-0.000000,-0.000001;;, + 24;3; 1.000000,-0.000000,-0.000001;;, + 25;3; 1.000000,-0.000000,-0.000001;;, + 26;3; 1.000000,-0.000000,-0.000000;;, + 27;3; 1.000000,-0.000000,-0.000000;;, + 28;3; 1.000000,-0.000000,-0.000000;;, + 29;3; 1.000000,-0.000000,-0.000000;;, + 30;3; 1.000000,-0.000000,-0.000000;;, + 31;3; 1.000000,-0.000000,-0.000001;;, + 32;3; 1.000000,-0.000000,-0.000001;;, + 33;3; 1.000000,-0.000000,-0.000001;;, + 34;3; 1.000000,-0.000000,-0.000001;;, + 35;3; 1.000000,-0.000000,-0.000001;;, + 36;3; 1.000000,-0.000000,-0.000001;;, + 37;3; 1.000000,-0.000000,-0.000001;;, + 38;3; 1.000000,-0.000000,-0.000001;;, + 39;3; 1.000000,-0.000000,-0.000001;;, + 40;3; 1.000000, 0.000000,-0.000001;;, + 41;3; 1.000000,-0.000000,-0.000001;;, + 42;3; 1.000000,-0.000000,-0.000001;;, + 43;3; 1.000000,-0.000000,-0.000001;;, + 44;3; 1.000000,-0.000000,-0.000001;;, + 45;3; 1.000000,-0.000000,-0.000001;;, + 46;3; 1.000000,-0.000000,-0.000001;;, + 47;3; 1.000000,-0.000000,-0.000001;;, + 48;3; 1.000000,-0.000000,-0.000001;;, + 49;3; 1.000000,-0.000000,-0.000001;;, + 50;3; 1.000000,-0.000000,-0.000000;;, + 51;3; 1.000000,-0.000000,-0.000000;;, + 52;3; 1.000000,-0.000000,-0.000000;;, + 53;3; 1.000000,-0.000000,-0.000000;;, + 54;3; 1.000000,-0.000000,-0.000000;;, + 55;3; 1.000000,-0.000000,-0.000001;;, + 56;3; 1.000000,-0.000000,-0.000001;;, + 57;3; 1.000000,-0.000000,-0.000001;;, + 58;3; 1.000000,-0.000000,-0.000001;;, + 59;3; 1.000000,-0.000000,-0.000001;;, + 60;3; 1.000000,-0.000000,-0.000001;;, + 61;3; 1.000000,-0.000000,-0.000001;;, + 62;3; 1.000000,-0.000000,-0.000001;;, + 63;3; 1.000000,-0.000000,-0.000001;;, + 64;3; 1.000000,-0.000000,-0.000001;;, + 65;3; 1.000000,-0.000000,-0.000001;;, + 66;3; 1.000000,-0.000000,-0.000001;;, + 67;3; 1.000000,-0.000000,-0.000000;;, + 68;3; 1.000000,-0.000000,-0.000000;;, + 69;3; 1.000000,-0.000000,-0.000000;;, + 70;3; 1.000000,-0.000000,-0.000000;;, + 71;3; 1.000000,-0.000000,-0.000000;;, + 72;3; 1.000000,-0.000000,-0.000000;;, + 73;3; 1.000000,-0.000000,-0.000000;;, + 74;3; 1.000000,-0.000000,-0.000001;;, + 75;3; 1.000000,-0.000000,-0.000001;;, + 76;3; 1.000000,-0.000000,-0.000001;;, + 77;3; 1.000000,-0.000000,-0.000001;;, + 78;3; 1.000000,-0.000000,-0.000001;;, + 79;3; 1.000000,-0.000000,-0.000001;;, + 80;3; 1.000000, 0.000000,-0.000001;;, + 81;3; 1.000000, 0.000000,-0.000001;;, + 82;3; 1.000000,-0.000000,-0.000001;;, + 83;3; 1.000000,-0.000000,-0.000001;;, + 84;3; 1.000000,-0.000000,-0.000001;;, + 85;3; 1.000000,-0.000000,-0.000001;;, + 86;3; 1.000000,-0.000000,-0.000001;;, + 87;3; 1.000000,-0.000000,-0.000001;;, + 88;3; 1.000000,-0.000000,-0.000001;;, + 89;3; 1.000000,-0.000000,-0.000001;;, + 90;3; 1.000000,-0.000000,-0.000001;;, + 91;3; 1.000000,-0.000000,-0.000001;;, + 92;3; 1.000000,-0.000000,-0.000001;;, + 93;3; 1.000000,-0.000000,-0.000001;;, + 94;3; 1.000000,-0.000000,-0.000001;;, + 95;3; 1.000000,-0.000000,-0.000001;;, + 96;3; 1.000000,-0.000000,-0.000001;;, + 97;3; 1.000000,-0.000000,-0.000001;;, + 98;3; 1.000000,-0.000000,-0.000001;;, + 99;3; 1.000000,-0.000000,-0.000001;;, + 100;3; 1.000000,-0.000000,-0.000001;;, + 101;3; 1.000000,-0.000000,-0.000001;;, + 102;3; 1.000000,-0.000000,-0.000001;;, + 103;3; 1.000000,-0.000000,-0.000001;;, + 104;3; 1.000000,-0.000000,-0.000001;;, + 105;3; 1.000000,-0.000000,-0.000001;;, + 106;3; 1.000000,-0.000000,-0.000001;;, + 107;3; 1.000000,-0.000000,-0.000001;;, + 108;3; 1.000000,-0.000000,-0.000001;;, + 109;3; 1.000000,-0.000000,-0.000001;;, + 110;3; 1.000000,-0.000000,-0.000001;;, + 111;3; 1.000000,-0.000000,-0.000001;;, + 112;3; 1.000000,-0.000000,-0.000001;;, + 113;3; 1.000000,-0.000000,-0.000001;;, + 114;3; 1.000000,-0.000000,-0.000001;;, + 115;3; 1.000000,-0.000000,-0.000001;;, + 116;3; 1.000000,-0.000000,-0.000001;;, + 117;3; 1.000000,-0.000000,-0.000001;;, + 118;3; 1.000000,-0.000000,-0.000001;;, + 119;3; 1.000000,-0.000000,-0.000001;;, + 120;3; 1.000000,-0.000000,-0.000001;;, + 121;3; 1.000000, 0.000000,-0.000001;;, + 122;3; 1.000000,-0.000000,-0.000001;;, + 123;3; 1.000000,-0.000000,-0.000001;;, + 124;3; 1.000000,-0.000000,-0.000001;;, + 125;3; 1.000000,-0.000000,-0.000001;;, + 126;3; 1.000000,-0.000000,-0.000001;;, + 127;3; 1.000000,-0.000000,-0.000001;;, + 128;3; 1.000000,-0.000000,-0.000001;;, + 129;3; 1.000000,-0.000000,-0.000001;;, + 130;3; 1.000000,-0.000000,-0.000001;;, + 131;3; 1.000000,-0.000000,-0.000001;;, + 132;3; 1.000000,-0.000000,-0.000001;;, + 133;3; 1.000000,-0.000000,-0.000001;;, + 134;3; 1.000000,-0.000000,-0.000001;;, + 135;3; 1.000000,-0.000000,-0.000001;;, + 136;3; 1.000000,-0.000000,-0.000001;;, + 137;3; 1.000000,-0.000000,-0.000001;;, + 138;3; 1.000000,-0.000000,-0.000001;;, + 139;3; 1.000000,-0.000000,-0.000001;;, + 140;3; 1.000000,-0.000000,-0.000001;;, + 141;3; 1.000000,-0.000000,-0.000001;;, + 142;3; 1.000000,-0.000000,-0.000001;;, + 143;3; 1.000000,-0.000000,-0.000001;;, + 144;3; 1.000000,-0.000000,-0.000001;;, + 145;3; 1.000000,-0.000000,-0.000001;;, + 146;3; 1.000000,-0.000000,-0.000001;;, + 147;3; 1.000000,-0.000000,-0.000001;;, + 148;3; 1.000000,-0.000000,-0.000001;;, + 149;3; 1.000000,-0.000000,-0.000001;;, + 150;3; 1.000000,-0.000000,-0.000001;;, + 151;3; 1.000000,-0.000000,-0.000001;;, + 152;3; 1.000000,-0.000000,-0.000001;;, + 153;3; 1.000000,-0.000000,-0.000001;;, + 154;3; 1.000000,-0.000000,-0.000001;;, + 155;3; 1.000000,-0.000000,-0.000001;;, + 156;3; 1.000000,-0.000000,-0.000001;;, + 157;3; 1.000000,-0.000000,-0.000001;;, + 158;3; 1.000000,-0.000000,-0.000001;;, + 159;3; 1.000000,-0.000000,-0.000001;;, + 160;3; 1.000000,-0.000000,-0.000001;;, + 161;3; 1.000000, 0.000000,-0.000001;;, + 162;3; 1.000000,-0.000000,-0.000000;;, + 163;3; 1.000000,-0.000000,-0.000000;;, + 164;3; 1.000000,-0.000000,-0.000000;;, + 165;3; 1.000000,-0.000000,-0.000000;;, + 166;3; 1.000000,-0.000000,-0.000000;;, + 167;3; 1.000000,-0.000000,-0.000000;;, + 168;3; 1.000000, 0.000000,-0.000001;;, + 169;3; 1.000000, 0.000000,-0.000001;;, + 170;3; 1.000000, 0.000000,-0.000001;;, + 171;3; 1.000000, 0.000000,-0.000001;;, + 172;3; 1.000000, 0.000000,-0.000001;;, + 173;3; 1.000000, 0.000000,-0.000001;;, + 174;3; 1.000000, 0.000000,-0.000001;;, + 175;3; 1.000000, 0.000000,-0.000001;;, + 176;3; 1.000000, 0.000000,-0.000001;;, + 177;3; 1.000000, 0.000000,-0.000001;;, + 178;3; 1.000000, 0.000000,-0.000001;;, + 179;3; 1.000000, 0.000000,-0.000001;;, + 180;3; 1.000000, 0.000000,-0.000001;;, + 181;3; 1.000000, 0.000000,-0.000001;;, + 182;3; 1.000000, 0.000000,-0.000001;;, + 183;3; 1.000000, 0.000000,-0.000001;;, + 184;3; 1.000000, 0.000000,-0.000001;;, + 185;3; 1.000000, 0.000000,-0.000001;;, + 186;3; 1.000000, 0.000000,-0.000001;;, + 187;3; 1.000000, 0.000000,-0.000001;;, + 188;3; 1.000000, 0.000000,-0.000001;;; + } + } + Animation { + {Armature_Leg_Left} + AnimationKey { // Rotation + 0; + 189; + 0;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 1;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 2;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 3;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 4;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 5;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 6;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 7;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 8;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 9;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 10;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 11;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 12;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 13;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 14;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 15;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 16;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 17;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 18;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 19;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 20;4;-0.043619, 0.999048,-0.000000,-0.000000;;, + 21;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 22;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 23;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 24;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 25;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 26;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 27;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 28;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 29;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 30;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 31;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 32;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 33;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 34;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 35;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 36;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 37;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 38;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 39;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 40;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 41;4;-0.000240, 0.999995,-0.000000,-0.000000;;, + 42;4;-0.000967, 0.999979,-0.000000,-0.000000;;, + 43;4;-0.002182, 0.999952,-0.000000,-0.000000;;, + 44;4;-0.003877, 0.999915,-0.000000,-0.000000;;, + 45;4;-0.006032, 0.999868,-0.000000,-0.000000;;, + 46;4;-0.008609, 0.999812,-0.000000,-0.000000;;, + 47;4;-0.011555, 0.999748,-0.000000,-0.000000;;, + 48;4;-0.014798, 0.999677,-0.000000,-0.000000;;, + 49;4;-0.018250, 0.999602,-0.000000,-0.000000;;, + 50;4;-0.021810, 0.999524,-0.000000,-0.000000;;, + 51;4;-0.025369, 0.999446,-0.000000,-0.000000;;, + 52;4;-0.028821, 0.999371,-0.000000,-0.000000;;, + 53;4;-0.032064, 0.999300,-0.000000,-0.000000;;, + 54;4;-0.035010, 0.999236,-0.000000,-0.000000;;, + 55;4;-0.037587, 0.999180,-0.000000,-0.000000;;, + 56;4;-0.039742, 0.999133,-0.000000,-0.000000;;, + 57;4;-0.041437, 0.999096,-0.000000,-0.000000;;, + 58;4;-0.042652, 0.999069,-0.000000,-0.000000;;, + 59;4;-0.043379, 0.999053,-0.000000,-0.000000;;, + 60;4;-0.043619, 0.999048,-0.000000,-0.000000;;, + 61;4;-0.043616, 0.999053,-0.000000,-0.000000;;, + 62;4;-0.043594, 0.999067,-0.000000,-0.000000;;, + 63;4;-0.043536, 0.999089,-0.000000,-0.000000;;, + 64;4;-0.043427, 0.999117,-0.000000,-0.000000;;, + 65;4;-0.043249, 0.999151,-0.000000,-0.000000;;, + 66;4;-0.042989, 0.999191,-0.000000,-0.000000;;, + 67;4;-0.042626, 0.999235,-0.000000,-0.000000;;, + 68;4;-0.042144, 0.999283,-0.000000,-0.000000;;, + 69;4;-0.041519, 0.999336,-0.000000,-0.000000;;, + 70;4;-0.040725, 0.999391,-0.000000,-0.000000;;, + 71;4;-0.039732, 0.999450,-0.000000,-0.000000;;, + 72;4;-0.038501, 0.999511,-0.000000,-0.000000;;, + 73;4;-0.036980, 0.999575,-0.000000,-0.000000;;, + 74;4;-0.035101, 0.999640,-0.000000,-0.000000;;, + 75;4;-0.032769, 0.999707,-0.000000,-0.000000;;, + 76;4;-0.029842, 0.999774,-0.000000,-0.000000;;, + 77;4;-0.026086, 0.999841,-0.000000,-0.000000;;, + 78;4;-0.021070, 0.999906,-0.000000,-0.000000;;, + 79;4;-0.013794, 0.999964,-0.000000,-0.000000;;, + 80;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 81;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 82;4; 0.705874, 0.708245, 0.000000,-0.000000;;, + 83;4; 0.703907, 0.710101, 0.000000,-0.000000;;, + 84;4; 0.701752, 0.712152, 0.000000,-0.000000;;, + 85;4; 0.699534, 0.714271, 0.000000,-0.000000;;, + 86;4; 0.697308, 0.716402, 0.000000,-0.000000;;, + 87;4; 0.695107, 0.718513, 0.000000,-0.000000;;, + 88;4; 0.692952, 0.720584, 0.000000,-0.000000;;, + 89;4; 0.690857, 0.722597, 0.000000,-0.000000;;, + 90;4; 0.688837, 0.724539, 0.000000,-0.000000;;, + 91;4; 0.686904, 0.726399, 0.000000,-0.000000;;, + 92;4; 0.685070, 0.728163, 0.000000,-0.000000;;, + 93;4; 0.683348, 0.729820, 0.000000,-0.000000;;, + 94;4; 0.681750, 0.731358, 0.000000,-0.000000;;, + 95;4; 0.680291, 0.732761, 0.000000,-0.000000;;, + 96;4; 0.678987, 0.734015, 0.000000,-0.000000;;, + 97;4; 0.677857, 0.735101, 0.000000,-0.000000;;, + 98;4; 0.676923, 0.735998, 0.000000,-0.000000;;, + 99;4; 0.676211, 0.736682, 0.000000,-0.000000;;, + 100;4; 0.675754, 0.737121, 0.000000,-0.000000;;, + 101;4; 0.675590, 0.737277, 0.000000,-0.000000;;, + 102;4; 0.675764, 0.737111, 0.000000,-0.000000;;, + 103;4; 0.676289, 0.736609, 0.000000,-0.000000;;, + 104;4; 0.677167, 0.735768, 0.000000,-0.000000;;, + 105;4; 0.678392, 0.734595, 0.000000,-0.000000;;, + 106;4; 0.679949, 0.733105, 0.000000,-0.000000;;, + 107;4; 0.681811, 0.731323, 0.000000,-0.000000;;, + 108;4; 0.683940, 0.729285, 0.000000,-0.000000;;, + 109;4; 0.686283, 0.727042, 0.000000,-0.000000;;, + 110;4; 0.688777, 0.724654, 0.000000,-0.000000;;, + 111;4; 0.691349, 0.722192, 0.000000,-0.000000;;, + 112;4; 0.693920, 0.719730, 0.000000,-0.000000;;, + 113;4; 0.696415, 0.717342, 0.000000,-0.000000;;, + 114;4; 0.698758, 0.715099, 0.000000,-0.000000;;, + 115;4; 0.700886, 0.713062, 0.000000,-0.000000;;, + 116;4; 0.702749, 0.711279, 0.000000,-0.000000;;, + 117;4; 0.704305, 0.709789, 0.000000,-0.000000;;, + 118;4; 0.705530, 0.708616, 0.000000,-0.000000;;, + 119;4; 0.706408, 0.707776, 0.000000,-0.000000;;, + 120;4; 0.706933, 0.707273, 0.000000,-0.000000;;, + 121;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 122;4; 0.706933, 0.707273, 0.000000,-0.000000;;, + 123;4; 0.706408, 0.707776, 0.000000,-0.000000;;, + 124;4; 0.705530, 0.708616, 0.000000,-0.000000;;, + 125;4; 0.704305, 0.709789, 0.000000,-0.000000;;, + 126;4; 0.702749, 0.711279, 0.000000,-0.000000;;, + 127;4; 0.700886, 0.713062, 0.000000,-0.000000;;, + 128;4; 0.698758, 0.715099, 0.000000,-0.000000;;, + 129;4; 0.696415, 0.717342, 0.000000,-0.000000;;, + 130;4; 0.693920, 0.719730, 0.000000,-0.000000;;, + 131;4; 0.691349, 0.722192, 0.000000,-0.000000;;, + 132;4; 0.688777, 0.724654, 0.000000,-0.000000;;, + 133;4; 0.686283, 0.727042, 0.000000,-0.000000;;, + 134;4; 0.683940, 0.729285, 0.000000,-0.000000;;, + 135;4; 0.681811, 0.731323, 0.000000,-0.000000;;, + 136;4; 0.679949, 0.733105, 0.000000,-0.000000;;, + 137;4; 0.678392, 0.734596, 0.000000,-0.000000;;, + 138;4; 0.677167, 0.735768, 0.000000,-0.000000;;, + 139;4; 0.676289, 0.736609, 0.000000,-0.000000;;, + 140;4; 0.675764, 0.737111, 0.000000,-0.000000;;, + 141;4; 0.675590, 0.737277, 0.000000,-0.000000;;, + 142;4; 0.675754, 0.737121, 0.000000,-0.000000;;, + 143;4; 0.676211, 0.736682, 0.000000,-0.000000;;, + 144;4; 0.676923, 0.735998, 0.000000,-0.000000;;, + 145;4; 0.677857, 0.735101, 0.000000,-0.000000;;, + 146;4; 0.678987, 0.734015, 0.000000,-0.000000;;, + 147;4; 0.680291, 0.732761, 0.000000,-0.000000;;, + 148;4; 0.681750, 0.731357, 0.000000,-0.000000;;, + 149;4; 0.683348, 0.729820, 0.000000,-0.000000;;, + 150;4; 0.685070, 0.728162, 0.000000,-0.000000;;, + 151;4; 0.686904, 0.726398, 0.000000,-0.000000;;, + 152;4; 0.688837, 0.724539, 0.000000,-0.000000;;, + 153;4; 0.690857, 0.722596, 0.000000,-0.000000;;, + 154;4; 0.692952, 0.720583, 0.000000,-0.000000;;, + 155;4; 0.695107, 0.718512, 0.000000,-0.000000;;, + 156;4; 0.697308, 0.716401, 0.000000,-0.000000;;, + 157;4; 0.699534, 0.714270, 0.000000,-0.000000;;, + 158;4; 0.701752, 0.712151, 0.000000,-0.000000;;, + 159;4; 0.703907, 0.710100, 0.000000,-0.000000;;, + 160;4; 0.705874, 0.708244, 0.000000,-0.000000;;, + 161;4; 0.707107, 0.707107, 0.000000,-0.000000;;, + 162;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 163;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 164;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 165;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 166;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 167;4; 0.000000, 0.991445,-0.130526,-0.000000;;, + 168;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 169;4;-0.034052, 0.993234,-0.000000,-0.000000;;, + 170;4;-0.129903, 0.974175,-0.000000,-0.000000;;, + 171;4;-0.252901, 0.949704,-0.000000,-0.000000;;, + 172;4;-0.348675, 0.930646,-0.000000,-0.000000;;, + 173;4;-0.382683, 0.923880,-0.000000,-0.000000;;, + 174;4;-0.361005, 0.930646,-0.000000,-0.000000;;, + 175;4;-0.294618, 0.949704,-0.000000,-0.000000;;, + 176;4;-0.194899, 0.974175,-0.000000,-0.000000;;, + 177;4;-0.088939, 0.993234,-0.000000,-0.000000;;, + 178;4; 0.000000, 1.000000,-0.000000,-0.000000;;, + 179;4; 0.088939, 0.993234, 0.000000,-0.000000;;, + 180;4; 0.194899, 0.974175, 0.000000,-0.000000;;, + 181;4; 0.294618, 0.949704, 0.000000,-0.000000;;, + 182;4; 0.361005, 0.930646, 0.000000,-0.000000;;, + 183;4; 0.382684, 0.923880, 0.000000,-0.000000;;, + 184;4; 0.348675, 0.930646, 0.000000,-0.000000;;, + 185;4; 0.252901, 0.949704, 0.000000,-0.000000;;, + 186;4; 0.129904, 0.974175, 0.000000,-0.000000;;, + 187;4; 0.034052, 0.993234, 0.000000,-0.000000;;, + 188;4; 0.000000, 1.000000,-0.000000,-0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 0.999999;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 0.999999;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 0.999999;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3;-1.000000, 0.000000,-0.000001;;, + 1;3;-1.000000,-0.000000,-0.000001;;, + 2;3;-1.000000,-0.000000,-0.000001;;, + 3;3;-1.000000,-0.000000,-0.000001;;, + 4;3;-1.000000,-0.000000,-0.000001;;, + 5;3;-1.000000,-0.000000,-0.000001;;, + 6;3;-1.000000,-0.000000,-0.000001;;, + 7;3;-1.000000,-0.000000,-0.000001;;, + 8;3;-1.000000,-0.000000,-0.000001;;, + 9;3;-1.000000,-0.000000,-0.000001;;, + 10;3;-1.000000,-0.000000,-0.000000;;, + 11;3;-1.000000,-0.000000,-0.000000;;, + 12;3;-1.000000,-0.000000,-0.000000;;, + 13;3;-1.000000,-0.000000,-0.000000;;, + 14;3;-1.000000,-0.000000,-0.000000;;, + 15;3;-1.000000,-0.000000,-0.000001;;, + 16;3;-1.000000,-0.000000,-0.000001;;, + 17;3;-1.000000,-0.000000,-0.000001;;, + 18;3;-1.000000,-0.000000,-0.000001;;, + 19;3;-1.000000,-0.000000,-0.000001;;, + 20;3;-1.000000,-0.000000,-0.000001;;, + 21;3;-1.000000,-0.000000,-0.000001;;, + 22;3;-1.000000,-0.000000,-0.000000;;, + 23;3;-1.000000,-0.000000,-0.000001;;, + 24;3;-1.000000,-0.000000,-0.000001;;, + 25;3;-1.000000,-0.000000,-0.000001;;, + 26;3;-1.000000,-0.000000,-0.000000;;, + 27;3;-1.000000,-0.000000,-0.000000;;, + 28;3;-1.000000,-0.000000,-0.000000;;, + 29;3;-1.000000,-0.000000,-0.000000;;, + 30;3;-1.000000,-0.000000,-0.000000;;, + 31;3;-1.000000,-0.000000,-0.000001;;, + 32;3;-1.000000,-0.000000,-0.000001;;, + 33;3;-1.000000,-0.000000,-0.000001;;, + 34;3;-1.000000,-0.000000,-0.000001;;, + 35;3;-1.000000,-0.000000,-0.000001;;, + 36;3;-1.000000,-0.000000,-0.000001;;, + 37;3;-1.000000,-0.000000,-0.000001;;, + 38;3;-1.000000,-0.000000,-0.000001;;, + 39;3;-1.000000,-0.000000,-0.000001;;, + 40;3;-1.000000, 0.000000,-0.000001;;, + 41;3;-1.000000,-0.000000,-0.000001;;, + 42;3;-1.000000,-0.000000,-0.000001;;, + 43;3;-1.000000,-0.000000,-0.000001;;, + 44;3;-1.000000,-0.000000,-0.000001;;, + 45;3;-1.000000,-0.000000,-0.000001;;, + 46;3;-1.000000,-0.000000,-0.000001;;, + 47;3;-1.000000,-0.000000,-0.000001;;, + 48;3;-1.000000,-0.000000,-0.000001;;, + 49;3;-1.000000,-0.000000,-0.000001;;, + 50;3;-1.000000,-0.000000,-0.000000;;, + 51;3;-1.000000,-0.000000,-0.000000;;, + 52;3;-1.000000,-0.000000,-0.000000;;, + 53;3;-1.000000,-0.000000,-0.000000;;, + 54;3;-1.000000,-0.000000,-0.000000;;, + 55;3;-1.000000,-0.000000,-0.000001;;, + 56;3;-1.000000,-0.000000,-0.000001;;, + 57;3;-1.000000,-0.000000,-0.000001;;, + 58;3;-1.000000,-0.000000,-0.000001;;, + 59;3;-1.000000,-0.000000,-0.000001;;, + 60;3;-1.000000,-0.000000,-0.000001;;, + 61;3;-1.000000,-0.000000,-0.000001;;, + 62;3;-1.000000,-0.000000,-0.000001;;, + 63;3;-1.000000,-0.000000,-0.000001;;, + 64;3;-1.000000,-0.000000,-0.000001;;, + 65;3;-1.000000,-0.000000,-0.000001;;, + 66;3;-1.000000,-0.000000,-0.000001;;, + 67;3;-1.000000,-0.000000,-0.000000;;, + 68;3;-1.000000,-0.000000,-0.000000;;, + 69;3;-1.000000,-0.000000,-0.000000;;, + 70;3;-1.000000,-0.000000,-0.000000;;, + 71;3;-1.000000,-0.000000,-0.000000;;, + 72;3;-1.000000,-0.000000,-0.000000;;, + 73;3;-1.000000,-0.000000,-0.000000;;, + 74;3;-1.000000,-0.000000,-0.000001;;, + 75;3;-1.000000,-0.000000,-0.000001;;, + 76;3;-1.000000,-0.000000,-0.000001;;, + 77;3;-1.000000,-0.000000,-0.000001;;, + 78;3;-1.000000,-0.000000,-0.000001;;, + 79;3;-1.000000,-0.000000,-0.000001;;, + 80;3;-1.000000, 0.000000,-0.000001;;, + 81;3;-1.000000, 0.000000,-0.000001;;, + 82;3;-1.000000,-0.000000,-0.000001;;, + 83;3;-1.000000,-0.000000,-0.000001;;, + 84;3;-1.000000,-0.000000,-0.000001;;, + 85;3;-1.000000,-0.000000,-0.000001;;, + 86;3;-1.000000,-0.000000,-0.000001;;, + 87;3;-1.000000,-0.000000,-0.000001;;, + 88;3;-1.000000,-0.000000,-0.000001;;, + 89;3;-1.000000,-0.000000,-0.000001;;, + 90;3;-1.000000,-0.000000,-0.000001;;, + 91;3;-1.000000,-0.000000,-0.000001;;, + 92;3;-1.000000,-0.000000,-0.000001;;, + 93;3;-1.000000,-0.000000,-0.000001;;, + 94;3;-1.000000,-0.000000,-0.000001;;, + 95;3;-1.000000,-0.000000,-0.000001;;, + 96;3;-1.000000,-0.000000,-0.000001;;, + 97;3;-1.000000,-0.000000,-0.000001;;, + 98;3;-1.000000,-0.000000,-0.000001;;, + 99;3;-1.000000,-0.000000,-0.000001;;, + 100;3;-1.000000,-0.000000,-0.000001;;, + 101;3;-1.000000,-0.000000,-0.000001;;, + 102;3;-1.000000,-0.000000,-0.000001;;, + 103;3;-1.000000,-0.000000,-0.000001;;, + 104;3;-1.000000,-0.000000,-0.000001;;, + 105;3;-1.000000,-0.000000,-0.000001;;, + 106;3;-1.000000,-0.000000,-0.000001;;, + 107;3;-1.000000,-0.000000,-0.000001;;, + 108;3;-1.000000,-0.000000,-0.000001;;, + 109;3;-1.000000,-0.000000,-0.000001;;, + 110;3;-1.000000,-0.000000,-0.000001;;, + 111;3;-1.000000,-0.000000,-0.000001;;, + 112;3;-1.000000,-0.000000,-0.000001;;, + 113;3;-1.000000,-0.000000,-0.000001;;, + 114;3;-1.000000,-0.000000,-0.000001;;, + 115;3;-1.000000,-0.000000,-0.000001;;, + 116;3;-1.000000,-0.000000,-0.000001;;, + 117;3;-1.000000,-0.000000,-0.000001;;, + 118;3;-1.000000,-0.000000,-0.000001;;, + 119;3;-1.000000,-0.000000,-0.000001;;, + 120;3;-1.000000,-0.000000,-0.000001;;, + 121;3;-1.000000, 0.000000,-0.000001;;, + 122;3;-1.000000,-0.000000,-0.000001;;, + 123;3;-1.000000,-0.000000,-0.000001;;, + 124;3;-1.000000,-0.000000,-0.000001;;, + 125;3;-1.000000,-0.000000,-0.000001;;, + 126;3;-1.000000,-0.000000,-0.000001;;, + 127;3;-1.000000,-0.000000,-0.000001;;, + 128;3;-1.000000,-0.000000,-0.000001;;, + 129;3;-1.000000,-0.000000,-0.000001;;, + 130;3;-1.000000,-0.000000,-0.000001;;, + 131;3;-1.000000,-0.000000,-0.000001;;, + 132;3;-1.000000,-0.000000,-0.000001;;, + 133;3;-1.000000,-0.000000,-0.000001;;, + 134;3;-1.000000,-0.000000,-0.000001;;, + 135;3;-1.000000,-0.000000,-0.000001;;, + 136;3;-1.000000,-0.000000,-0.000001;;, + 137;3;-1.000000,-0.000000,-0.000001;;, + 138;3;-1.000000,-0.000000,-0.000001;;, + 139;3;-1.000000,-0.000000,-0.000001;;, + 140;3;-1.000000,-0.000000,-0.000001;;, + 141;3;-1.000000,-0.000000,-0.000001;;, + 142;3;-1.000000,-0.000000,-0.000001;;, + 143;3;-1.000000,-0.000000,-0.000001;;, + 144;3;-1.000000,-0.000000,-0.000001;;, + 145;3;-1.000000,-0.000000,-0.000001;;, + 146;3;-1.000000,-0.000000,-0.000001;;, + 147;3;-1.000000,-0.000000,-0.000001;;, + 148;3;-1.000000,-0.000000,-0.000001;;, + 149;3;-1.000000,-0.000000,-0.000001;;, + 150;3;-1.000000,-0.000000,-0.000001;;, + 151;3;-1.000000,-0.000000,-0.000001;;, + 152;3;-1.000000,-0.000000,-0.000001;;, + 153;3;-1.000000,-0.000000,-0.000001;;, + 154;3;-1.000000,-0.000000,-0.000001;;, + 155;3;-1.000000,-0.000000,-0.000001;;, + 156;3;-1.000000,-0.000000,-0.000001;;, + 157;3;-1.000000,-0.000000,-0.000001;;, + 158;3;-1.000000,-0.000000,-0.000001;;, + 159;3;-1.000000,-0.000000,-0.000001;;, + 160;3;-1.000000,-0.000000,-0.000001;;, + 161;3;-1.000000, 0.000000,-0.000001;;, + 162;3;-1.000000,-0.000000,-0.000000;;, + 163;3;-1.000000,-0.000000,-0.000000;;, + 164;3;-1.000000,-0.000000,-0.000000;;, + 165;3;-1.000000,-0.000000,-0.000000;;, + 166;3;-1.000000,-0.000000,-0.000000;;, + 167;3;-1.000000,-0.000000,-0.000000;;, + 168;3;-1.000000, 0.000000,-0.000001;;, + 169;3;-1.000000, 0.000000,-0.000001;;, + 170;3;-1.000000, 0.000000,-0.000001;;, + 171;3;-1.000000, 0.000000,-0.000001;;, + 172;3;-1.000000, 0.000000,-0.000001;;, + 173;3;-1.000000, 0.000000,-0.000001;;, + 174;3;-1.000000, 0.000000,-0.000001;;, + 175;3;-1.000000, 0.000000,-0.000001;;, + 176;3;-1.000000, 0.000000,-0.000001;;, + 177;3;-1.000000, 0.000000,-0.000001;;, + 178;3;-1.000000, 0.000000,-0.000001;;, + 179;3;-1.000000, 0.000000,-0.000001;;, + 180;3;-1.000000, 0.000000,-0.000001;;, + 181;3;-1.000000, 0.000000,-0.000001;;, + 182;3;-1.000000, 0.000000,-0.000001;;, + 183;3;-1.000000, 0.000000,-0.000001;;, + 184;3;-1.000000, 0.000000,-0.000001;;, + 185;3;-1.000000, 0.000000,-0.000001;;, + 186;3;-1.000000, 0.000000,-0.000001;;, + 187;3;-1.000000, 0.000000,-0.000001;;, + 188;3;-1.000000, 0.000000,-0.000001;;; + } + } +} // End of AnimationSet ArmatureAction +AnimationSet Default_Action { + Animation { + {Player} + AnimationKey { // Rotation + 0; + 189; + 0;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 1;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 2;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 3;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 4;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 5;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 6;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 7;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 8;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 9;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 10;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 11;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 12;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 13;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 14;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 15;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 16;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 17;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 18;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 19;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 20;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 21;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 22;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 23;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 24;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 25;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 26;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 27;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 28;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 29;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 30;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 31;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 32;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 33;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 34;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 35;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 36;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 37;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 38;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 39;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 40;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 41;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 42;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 43;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 44;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 45;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 46;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 47;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 48;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 49;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 50;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 51;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 52;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 53;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 54;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 55;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 56;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 57;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 58;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 59;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 60;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 61;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 62;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 63;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 64;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 65;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 66;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 67;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 68;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 69;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 70;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 71;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 72;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 73;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 74;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 75;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 76;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 77;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 78;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 79;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 80;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 81;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 82;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 83;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 84;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 85;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 86;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 87;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 88;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 89;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 90;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 91;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 92;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 93;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 94;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 95;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 96;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 97;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 98;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 99;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 100;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 101;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 102;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 103;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 104;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 105;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 106;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 107;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 108;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 109;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 110;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 111;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 112;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 113;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 114;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 115;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 116;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 117;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 118;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 119;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 120;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 121;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 122;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 123;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 124;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 125;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 126;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 127;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 128;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 129;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 130;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 131;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 132;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 133;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 134;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 135;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 136;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 137;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 138;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 139;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 140;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 141;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 142;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 143;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 144;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 145;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 146;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 147;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 148;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 149;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 150;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 151;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 152;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 153;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 154;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 155;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 156;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 157;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 158;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 159;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 160;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 161;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 162;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 163;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 164;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 165;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 166;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 167;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 168;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 169;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 170;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 171;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 172;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 173;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 174;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 175;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 176;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 177;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 178;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 179;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 180;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 181;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 182;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 183;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 184;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 185;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 186;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 187;4;-1.000000, 0.000000, 0.000000, 0.000000;;, + 188;4;-1.000000, 0.000000, 0.000000, 0.000000;;; + } + AnimationKey { // Scale + 1; + 189; + 0;3; 1.000000, 1.000000, 1.000000;;, + 1;3; 1.000000, 1.000000, 1.000000;;, + 2;3; 1.000000, 1.000000, 1.000000;;, + 3;3; 1.000000, 1.000000, 1.000000;;, + 4;3; 1.000000, 1.000000, 1.000000;;, + 5;3; 1.000000, 1.000000, 1.000000;;, + 6;3; 1.000000, 1.000000, 1.000000;;, + 7;3; 1.000000, 1.000000, 1.000000;;, + 8;3; 1.000000, 1.000000, 1.000000;;, + 9;3; 1.000000, 1.000000, 1.000000;;, + 10;3; 1.000000, 1.000000, 1.000000;;, + 11;3; 1.000000, 1.000000, 1.000000;;, + 12;3; 1.000000, 1.000000, 1.000000;;, + 13;3; 1.000000, 1.000000, 1.000000;;, + 14;3; 1.000000, 1.000000, 1.000000;;, + 15;3; 1.000000, 1.000000, 1.000000;;, + 16;3; 1.000000, 1.000000, 1.000000;;, + 17;3; 1.000000, 1.000000, 1.000000;;, + 18;3; 1.000000, 1.000000, 1.000000;;, + 19;3; 1.000000, 1.000000, 1.000000;;, + 20;3; 1.000000, 1.000000, 1.000000;;, + 21;3; 1.000000, 1.000000, 1.000000;;, + 22;3; 1.000000, 1.000000, 1.000000;;, + 23;3; 1.000000, 1.000000, 1.000000;;, + 24;3; 1.000000, 1.000000, 1.000000;;, + 25;3; 1.000000, 1.000000, 1.000000;;, + 26;3; 1.000000, 1.000000, 1.000000;;, + 27;3; 1.000000, 1.000000, 1.000000;;, + 28;3; 1.000000, 1.000000, 1.000000;;, + 29;3; 1.000000, 1.000000, 1.000000;;, + 30;3; 1.000000, 1.000000, 1.000000;;, + 31;3; 1.000000, 1.000000, 1.000000;;, + 32;3; 1.000000, 1.000000, 1.000000;;, + 33;3; 1.000000, 1.000000, 1.000000;;, + 34;3; 1.000000, 1.000000, 1.000000;;, + 35;3; 1.000000, 1.000000, 1.000000;;, + 36;3; 1.000000, 1.000000, 1.000000;;, + 37;3; 1.000000, 1.000000, 1.000000;;, + 38;3; 1.000000, 1.000000, 1.000000;;, + 39;3; 1.000000, 1.000000, 1.000000;;, + 40;3; 1.000000, 1.000000, 1.000000;;, + 41;3; 1.000000, 1.000000, 1.000000;;, + 42;3; 1.000000, 1.000000, 1.000000;;, + 43;3; 1.000000, 1.000000, 1.000000;;, + 44;3; 1.000000, 1.000000, 1.000000;;, + 45;3; 1.000000, 1.000000, 1.000000;;, + 46;3; 1.000000, 1.000000, 1.000000;;, + 47;3; 1.000000, 1.000000, 1.000000;;, + 48;3; 1.000000, 1.000000, 1.000000;;, + 49;3; 1.000000, 1.000000, 1.000000;;, + 50;3; 1.000000, 1.000000, 1.000000;;, + 51;3; 1.000000, 1.000000, 1.000000;;, + 52;3; 1.000000, 1.000000, 1.000000;;, + 53;3; 1.000000, 1.000000, 1.000000;;, + 54;3; 1.000000, 1.000000, 1.000000;;, + 55;3; 1.000000, 1.000000, 1.000000;;, + 56;3; 1.000000, 1.000000, 1.000000;;, + 57;3; 1.000000, 1.000000, 1.000000;;, + 58;3; 1.000000, 1.000000, 1.000000;;, + 59;3; 1.000000, 1.000000, 1.000000;;, + 60;3; 1.000000, 1.000000, 1.000000;;, + 61;3; 1.000000, 1.000000, 1.000000;;, + 62;3; 1.000000, 1.000000, 1.000000;;, + 63;3; 1.000000, 1.000000, 1.000000;;, + 64;3; 1.000000, 1.000000, 1.000000;;, + 65;3; 1.000000, 1.000000, 1.000000;;, + 66;3; 1.000000, 1.000000, 1.000000;;, + 67;3; 1.000000, 1.000000, 1.000000;;, + 68;3; 1.000000, 1.000000, 1.000000;;, + 69;3; 1.000000, 1.000000, 1.000000;;, + 70;3; 1.000000, 1.000000, 1.000000;;, + 71;3; 1.000000, 1.000000, 1.000000;;, + 72;3; 1.000000, 1.000000, 1.000000;;, + 73;3; 1.000000, 1.000000, 1.000000;;, + 74;3; 1.000000, 1.000000, 1.000000;;, + 75;3; 1.000000, 1.000000, 1.000000;;, + 76;3; 1.000000, 1.000000, 1.000000;;, + 77;3; 1.000000, 1.000000, 1.000000;;, + 78;3; 1.000000, 1.000000, 1.000000;;, + 79;3; 1.000000, 1.000000, 1.000000;;, + 80;3; 1.000000, 1.000000, 1.000000;;, + 81;3; 1.000000, 1.000000, 1.000000;;, + 82;3; 1.000000, 1.000000, 1.000000;;, + 83;3; 1.000000, 1.000000, 1.000000;;, + 84;3; 1.000000, 1.000000, 1.000000;;, + 85;3; 1.000000, 1.000000, 1.000000;;, + 86;3; 1.000000, 1.000000, 1.000000;;, + 87;3; 1.000000, 1.000000, 1.000000;;, + 88;3; 1.000000, 1.000000, 1.000000;;, + 89;3; 1.000000, 1.000000, 1.000000;;, + 90;3; 1.000000, 1.000000, 1.000000;;, + 91;3; 1.000000, 1.000000, 1.000000;;, + 92;3; 1.000000, 1.000000, 1.000000;;, + 93;3; 1.000000, 1.000000, 1.000000;;, + 94;3; 1.000000, 1.000000, 1.000000;;, + 95;3; 1.000000, 1.000000, 1.000000;;, + 96;3; 1.000000, 1.000000, 1.000000;;, + 97;3; 1.000000, 1.000000, 1.000000;;, + 98;3; 1.000000, 1.000000, 1.000000;;, + 99;3; 1.000000, 1.000000, 1.000000;;, + 100;3; 1.000000, 1.000000, 1.000000;;, + 101;3; 1.000000, 1.000000, 1.000000;;, + 102;3; 1.000000, 1.000000, 1.000000;;, + 103;3; 1.000000, 1.000000, 1.000000;;, + 104;3; 1.000000, 1.000000, 1.000000;;, + 105;3; 1.000000, 1.000000, 1.000000;;, + 106;3; 1.000000, 1.000000, 1.000000;;, + 107;3; 1.000000, 1.000000, 1.000000;;, + 108;3; 1.000000, 1.000000, 1.000000;;, + 109;3; 1.000000, 1.000000, 1.000000;;, + 110;3; 1.000000, 1.000000, 1.000000;;, + 111;3; 1.000000, 1.000000, 1.000000;;, + 112;3; 1.000000, 1.000000, 1.000000;;, + 113;3; 1.000000, 1.000000, 1.000000;;, + 114;3; 1.000000, 1.000000, 1.000000;;, + 115;3; 1.000000, 1.000000, 1.000000;;, + 116;3; 1.000000, 1.000000, 1.000000;;, + 117;3; 1.000000, 1.000000, 1.000000;;, + 118;3; 1.000000, 1.000000, 1.000000;;, + 119;3; 1.000000, 1.000000, 1.000000;;, + 120;3; 1.000000, 1.000000, 1.000000;;, + 121;3; 1.000000, 1.000000, 1.000000;;, + 122;3; 1.000000, 1.000000, 1.000000;;, + 123;3; 1.000000, 1.000000, 1.000000;;, + 124;3; 1.000000, 1.000000, 1.000000;;, + 125;3; 1.000000, 1.000000, 1.000000;;, + 126;3; 1.000000, 1.000000, 1.000000;;, + 127;3; 1.000000, 1.000000, 1.000000;;, + 128;3; 1.000000, 1.000000, 1.000000;;, + 129;3; 1.000000, 1.000000, 1.000000;;, + 130;3; 1.000000, 1.000000, 1.000000;;, + 131;3; 1.000000, 1.000000, 1.000000;;, + 132;3; 1.000000, 1.000000, 1.000000;;, + 133;3; 1.000000, 1.000000, 1.000000;;, + 134;3; 1.000000, 1.000000, 1.000000;;, + 135;3; 1.000000, 1.000000, 1.000000;;, + 136;3; 1.000000, 1.000000, 1.000000;;, + 137;3; 1.000000, 1.000000, 1.000000;;, + 138;3; 1.000000, 1.000000, 1.000000;;, + 139;3; 1.000000, 1.000000, 1.000000;;, + 140;3; 1.000000, 1.000000, 1.000000;;, + 141;3; 1.000000, 1.000000, 1.000000;;, + 142;3; 1.000000, 1.000000, 1.000000;;, + 143;3; 1.000000, 1.000000, 1.000000;;, + 144;3; 1.000000, 1.000000, 1.000000;;, + 145;3; 1.000000, 1.000000, 1.000000;;, + 146;3; 1.000000, 1.000000, 1.000000;;, + 147;3; 1.000000, 1.000000, 1.000000;;, + 148;3; 1.000000, 1.000000, 1.000000;;, + 149;3; 1.000000, 1.000000, 1.000000;;, + 150;3; 1.000000, 1.000000, 1.000000;;, + 151;3; 1.000000, 1.000000, 1.000000;;, + 152;3; 1.000000, 1.000000, 1.000000;;, + 153;3; 1.000000, 1.000000, 1.000000;;, + 154;3; 1.000000, 1.000000, 1.000000;;, + 155;3; 1.000000, 1.000000, 1.000000;;, + 156;3; 1.000000, 1.000000, 1.000000;;, + 157;3; 1.000000, 1.000000, 1.000000;;, + 158;3; 1.000000, 1.000000, 1.000000;;, + 159;3; 1.000000, 1.000000, 1.000000;;, + 160;3; 1.000000, 1.000000, 1.000000;;, + 161;3; 1.000000, 1.000000, 1.000000;;, + 162;3; 1.000000, 1.000000, 1.000000;;, + 163;3; 1.000000, 1.000000, 1.000000;;, + 164;3; 1.000000, 1.000000, 1.000000;;, + 165;3; 1.000000, 1.000000, 1.000000;;, + 166;3; 1.000000, 1.000000, 1.000000;;, + 167;3; 1.000000, 1.000000, 1.000000;;, + 168;3; 1.000000, 1.000000, 1.000000;;, + 169;3; 1.000000, 1.000000, 1.000000;;, + 170;3; 1.000000, 1.000000, 1.000000;;, + 171;3; 1.000000, 1.000000, 1.000000;;, + 172;3; 1.000000, 1.000000, 1.000000;;, + 173;3; 1.000000, 1.000000, 1.000000;;, + 174;3; 1.000000, 1.000000, 1.000000;;, + 175;3; 1.000000, 1.000000, 1.000000;;, + 176;3; 1.000000, 1.000000, 1.000000;;, + 177;3; 1.000000, 1.000000, 1.000000;;, + 178;3; 1.000000, 1.000000, 1.000000;;, + 179;3; 1.000000, 1.000000, 1.000000;;, + 180;3; 1.000000, 1.000000, 1.000000;;, + 181;3; 1.000000, 1.000000, 1.000000;;, + 182;3; 1.000000, 1.000000, 1.000000;;, + 183;3; 1.000000, 1.000000, 1.000000;;, + 184;3; 1.000000, 1.000000, 1.000000;;, + 185;3; 1.000000, 1.000000, 1.000000;;, + 186;3; 1.000000, 1.000000, 1.000000;;, + 187;3; 1.000000, 1.000000, 1.000000;;, + 188;3; 1.000000, 1.000000, 1.000000;;; + } + AnimationKey { // Position + 2; + 189; + 0;3; 0.000000, 0.000000, 0.000000;;, + 1;3; 0.000000, 0.000000, 0.000000;;, + 2;3; 0.000000, 0.000000, 0.000000;;, + 3;3; 0.000000, 0.000000, 0.000000;;, + 4;3; 0.000000, 0.000000, 0.000000;;, + 5;3; 0.000000, 0.000000, 0.000000;;, + 6;3; 0.000000, 0.000000, 0.000000;;, + 7;3; 0.000000, 0.000000, 0.000000;;, + 8;3; 0.000000, 0.000000, 0.000000;;, + 9;3; 0.000000, 0.000000, 0.000000;;, + 10;3; 0.000000, 0.000000, 0.000000;;, + 11;3; 0.000000, 0.000000, 0.000000;;, + 12;3; 0.000000, 0.000000, 0.000000;;, + 13;3; 0.000000, 0.000000, 0.000000;;, + 14;3; 0.000000, 0.000000, 0.000000;;, + 15;3; 0.000000, 0.000000, 0.000000;;, + 16;3; 0.000000, 0.000000, 0.000000;;, + 17;3; 0.000000, 0.000000, 0.000000;;, + 18;3; 0.000000, 0.000000, 0.000000;;, + 19;3; 0.000000, 0.000000, 0.000000;;, + 20;3; 0.000000, 0.000000, 0.000000;;, + 21;3; 0.000000, 0.000000, 0.000000;;, + 22;3; 0.000000, 0.000000, 0.000000;;, + 23;3; 0.000000, 0.000000, 0.000000;;, + 24;3; 0.000000, 0.000000, 0.000000;;, + 25;3; 0.000000, 0.000000, 0.000000;;, + 26;3; 0.000000, 0.000000, 0.000000;;, + 27;3; 0.000000, 0.000000, 0.000000;;, + 28;3; 0.000000, 0.000000, 0.000000;;, + 29;3; 0.000000, 0.000000, 0.000000;;, + 30;3; 0.000000, 0.000000, 0.000000;;, + 31;3; 0.000000, 0.000000, 0.000000;;, + 32;3; 0.000000, 0.000000, 0.000000;;, + 33;3; 0.000000, 0.000000, 0.000000;;, + 34;3; 0.000000, 0.000000, 0.000000;;, + 35;3; 0.000000, 0.000000, 0.000000;;, + 36;3; 0.000000, 0.000000, 0.000000;;, + 37;3; 0.000000, 0.000000, 0.000000;;, + 38;3; 0.000000, 0.000000, 0.000000;;, + 39;3; 0.000000, 0.000000, 0.000000;;, + 40;3; 0.000000, 0.000000, 0.000000;;, + 41;3; 0.000000, 0.000000, 0.000000;;, + 42;3; 0.000000, 0.000000, 0.000000;;, + 43;3; 0.000000, 0.000000, 0.000000;;, + 44;3; 0.000000, 0.000000, 0.000000;;, + 45;3; 0.000000, 0.000000, 0.000000;;, + 46;3; 0.000000, 0.000000, 0.000000;;, + 47;3; 0.000000, 0.000000, 0.000000;;, + 48;3; 0.000000, 0.000000, 0.000000;;, + 49;3; 0.000000, 0.000000, 0.000000;;, + 50;3; 0.000000, 0.000000, 0.000000;;, + 51;3; 0.000000, 0.000000, 0.000000;;, + 52;3; 0.000000, 0.000000, 0.000000;;, + 53;3; 0.000000, 0.000000, 0.000000;;, + 54;3; 0.000000, 0.000000, 0.000000;;, + 55;3; 0.000000, 0.000000, 0.000000;;, + 56;3; 0.000000, 0.000000, 0.000000;;, + 57;3; 0.000000, 0.000000, 0.000000;;, + 58;3; 0.000000, 0.000000, 0.000000;;, + 59;3; 0.000000, 0.000000, 0.000000;;, + 60;3; 0.000000, 0.000000, 0.000000;;, + 61;3; 0.000000, 0.000000, 0.000000;;, + 62;3; 0.000000, 0.000000, 0.000000;;, + 63;3; 0.000000, 0.000000, 0.000000;;, + 64;3; 0.000000, 0.000000, 0.000000;;, + 65;3; 0.000000, 0.000000, 0.000000;;, + 66;3; 0.000000, 0.000000, 0.000000;;, + 67;3; 0.000000, 0.000000, 0.000000;;, + 68;3; 0.000000, 0.000000, 0.000000;;, + 69;3; 0.000000, 0.000000, 0.000000;;, + 70;3; 0.000000, 0.000000, 0.000000;;, + 71;3; 0.000000, 0.000000, 0.000000;;, + 72;3; 0.000000, 0.000000, 0.000000;;, + 73;3; 0.000000, 0.000000, 0.000000;;, + 74;3; 0.000000, 0.000000, 0.000000;;, + 75;3; 0.000000, 0.000000, 0.000000;;, + 76;3; 0.000000, 0.000000, 0.000000;;, + 77;3; 0.000000, 0.000000, 0.000000;;, + 78;3; 0.000000, 0.000000, 0.000000;;, + 79;3; 0.000000, 0.000000, 0.000000;;, + 80;3; 0.000000, 0.000000, 0.000000;;, + 81;3; 0.000000, 0.000000, 0.000000;;, + 82;3; 0.000000, 0.000000, 0.000000;;, + 83;3; 0.000000, 0.000000, 0.000000;;, + 84;3; 0.000000, 0.000000, 0.000000;;, + 85;3; 0.000000, 0.000000, 0.000000;;, + 86;3; 0.000000, 0.000000, 0.000000;;, + 87;3; 0.000000, 0.000000, 0.000000;;, + 88;3; 0.000000, 0.000000, 0.000000;;, + 89;3; 0.000000, 0.000000, 0.000000;;, + 90;3; 0.000000, 0.000000, 0.000000;;, + 91;3; 0.000000, 0.000000, 0.000000;;, + 92;3; 0.000000, 0.000000, 0.000000;;, + 93;3; 0.000000, 0.000000, 0.000000;;, + 94;3; 0.000000, 0.000000, 0.000000;;, + 95;3; 0.000000, 0.000000, 0.000000;;, + 96;3; 0.000000, 0.000000, 0.000000;;, + 97;3; 0.000000, 0.000000, 0.000000;;, + 98;3; 0.000000, 0.000000, 0.000000;;, + 99;3; 0.000000, 0.000000, 0.000000;;, + 100;3; 0.000000, 0.000000, 0.000000;;, + 101;3; 0.000000, 0.000000, 0.000000;;, + 102;3; 0.000000, 0.000000, 0.000000;;, + 103;3; 0.000000, 0.000000, 0.000000;;, + 104;3; 0.000000, 0.000000, 0.000000;;, + 105;3; 0.000000, 0.000000, 0.000000;;, + 106;3; 0.000000, 0.000000, 0.000000;;, + 107;3; 0.000000, 0.000000, 0.000000;;, + 108;3; 0.000000, 0.000000, 0.000000;;, + 109;3; 0.000000, 0.000000, 0.000000;;, + 110;3; 0.000000, 0.000000, 0.000000;;, + 111;3; 0.000000, 0.000000, 0.000000;;, + 112;3; 0.000000, 0.000000, 0.000000;;, + 113;3; 0.000000, 0.000000, 0.000000;;, + 114;3; 0.000000, 0.000000, 0.000000;;, + 115;3; 0.000000, 0.000000, 0.000000;;, + 116;3; 0.000000, 0.000000, 0.000000;;, + 117;3; 0.000000, 0.000000, 0.000000;;, + 118;3; 0.000000, 0.000000, 0.000000;;, + 119;3; 0.000000, 0.000000, 0.000000;;, + 120;3; 0.000000, 0.000000, 0.000000;;, + 121;3; 0.000000, 0.000000, 0.000000;;, + 122;3; 0.000000, 0.000000, 0.000000;;, + 123;3; 0.000000, 0.000000, 0.000000;;, + 124;3; 0.000000, 0.000000, 0.000000;;, + 125;3; 0.000000, 0.000000, 0.000000;;, + 126;3; 0.000000, 0.000000, 0.000000;;, + 127;3; 0.000000, 0.000000, 0.000000;;, + 128;3; 0.000000, 0.000000, 0.000000;;, + 129;3; 0.000000, 0.000000, 0.000000;;, + 130;3; 0.000000, 0.000000, 0.000000;;, + 131;3; 0.000000, 0.000000, 0.000000;;, + 132;3; 0.000000, 0.000000, 0.000000;;, + 133;3; 0.000000, 0.000000, 0.000000;;, + 134;3; 0.000000, 0.000000, 0.000000;;, + 135;3; 0.000000, 0.000000, 0.000000;;, + 136;3; 0.000000, 0.000000, 0.000000;;, + 137;3; 0.000000, 0.000000, 0.000000;;, + 138;3; 0.000000, 0.000000, 0.000000;;, + 139;3; 0.000000, 0.000000, 0.000000;;, + 140;3; 0.000000, 0.000000, 0.000000;;, + 141;3; 0.000000, 0.000000, 0.000000;;, + 142;3; 0.000000, 0.000000, 0.000000;;, + 143;3; 0.000000, 0.000000, 0.000000;;, + 144;3; 0.000000, 0.000000, 0.000000;;, + 145;3; 0.000000, 0.000000, 0.000000;;, + 146;3; 0.000000, 0.000000, 0.000000;;, + 147;3; 0.000000, 0.000000, 0.000000;;, + 148;3; 0.000000, 0.000000, 0.000000;;, + 149;3; 0.000000, 0.000000, 0.000000;;, + 150;3; 0.000000, 0.000000, 0.000000;;, + 151;3; 0.000000, 0.000000, 0.000000;;, + 152;3; 0.000000, 0.000000, 0.000000;;, + 153;3; 0.000000, 0.000000, 0.000000;;, + 154;3; 0.000000, 0.000000, 0.000000;;, + 155;3; 0.000000, 0.000000, 0.000000;;, + 156;3; 0.000000, 0.000000, 0.000000;;, + 157;3; 0.000000, 0.000000, 0.000000;;, + 158;3; 0.000000, 0.000000, 0.000000;;, + 159;3; 0.000000, 0.000000, 0.000000;;, + 160;3; 0.000000, 0.000000, 0.000000;;, + 161;3; 0.000000, 0.000000, 0.000000;;, + 162;3; 0.000000, 0.000000, 0.000000;;, + 163;3; 0.000000, 0.000000, 0.000000;;, + 164;3; 0.000000, 0.000000, 0.000000;;, + 165;3; 0.000000, 0.000000, 0.000000;;, + 166;3; 0.000000, 0.000000, 0.000000;;, + 167;3; 0.000000, 0.000000, 0.000000;;, + 168;3; 0.000000, 0.000000, 0.000000;;, + 169;3; 0.000000, 0.000000, 0.000000;;, + 170;3; 0.000000, 0.000000, 0.000000;;, + 171;3; 0.000000, 0.000000, 0.000000;;, + 172;3; 0.000000, 0.000000, 0.000000;;, + 173;3; 0.000000, 0.000000, 0.000000;;, + 174;3; 0.000000, 0.000000, 0.000000;;, + 175;3; 0.000000, 0.000000, 0.000000;;, + 176;3; 0.000000, 0.000000, 0.000000;;, + 177;3; 0.000000, 0.000000, 0.000000;;, + 178;3; 0.000000, 0.000000, 0.000000;;, + 179;3; 0.000000, 0.000000, 0.000000;;, + 180;3; 0.000000, 0.000000, 0.000000;;, + 181;3; 0.000000, 0.000000, 0.000000;;, + 182;3; 0.000000, 0.000000, 0.000000;;, + 183;3; 0.000000, 0.000000, 0.000000;;, + 184;3; 0.000000, 0.000000, 0.000000;;, + 185;3; 0.000000, 0.000000, 0.000000;;, + 186;3; 0.000000, 0.000000, 0.000000;;, + 187;3; 0.000000, 0.000000, 0.000000;;, + 188;3; 0.000000, 0.000000, 0.000000;;; + } + } +} // End of AnimationSet Default_Action diff --git a/mods/mobs/models/mobs_bunny.b3d b/mods/mobs/models/mobs_bunny.b3d new file mode 100644 index 0000000..ee053bd Binary files /dev/null and b/mods/mobs/models/mobs_bunny.b3d differ diff --git a/mods/mobs/models/mobs_dungeon_master.b3d b/mods/mobs/models/mobs_dungeon_master.b3d new file mode 100644 index 0000000..f45e760 Binary files /dev/null and b/mods/mobs/models/mobs_dungeon_master.b3d differ diff --git a/mods/mobs/models/mobs_kitten.b3d b/mods/mobs/models/mobs_kitten.b3d new file mode 100644 index 0000000..c2478fe Binary files /dev/null and b/mods/mobs/models/mobs_kitten.b3d differ diff --git a/mods/mobs/models/mobs_oerkki.b3d b/mods/mobs/models/mobs_oerkki.b3d new file mode 100644 index 0000000..6290af3 Binary files /dev/null and b/mods/mobs/models/mobs_oerkki.b3d differ diff --git a/mods/mobs/models/mobs_rat.b3d b/mods/mobs/models/mobs_rat.b3d new file mode 100644 index 0000000..64376b9 Binary files /dev/null and b/mods/mobs/models/mobs_rat.b3d differ diff --git a/mods/mobs/models/mobs_sheep.b3d b/mods/mobs/models/mobs_sheep.b3d new file mode 100644 index 0000000..bcf2dfc Binary files /dev/null and b/mods/mobs/models/mobs_sheep.b3d differ diff --git a/mods/mobs/models/mobs_sheep_shaved.b3d b/mods/mobs/models/mobs_sheep_shaved.b3d new file mode 100644 index 0000000..857b406 Binary files /dev/null and b/mods/mobs/models/mobs_sheep_shaved.b3d differ diff --git a/mods/mobs/models/zombie_crawler.b3d b/mods/mobs/models/zombie_crawler.b3d new file mode 100644 index 0000000..ac36890 Binary files /dev/null and b/mods/mobs/models/zombie_crawler.b3d differ diff --git a/mods/mobs/models/zombie_normal.b3d b/mods/mobs/models/zombie_normal.b3d new file mode 100644 index 0000000..9a96df4 Binary files /dev/null and b/mods/mobs/models/zombie_normal.b3d differ diff --git a/mods/mobs/models/zombie_one-arm.b3d b/mods/mobs/models/zombie_one-arm.b3d new file mode 100644 index 0000000..4cbdc5a Binary files /dev/null and b/mods/mobs/models/zombie_one-arm.b3d differ diff --git a/mods/mobs/nodes.lua b/mods/mobs/nodes.lua new file mode 100644 index 0000000..09ed6bf --- /dev/null +++ b/mods/mobs/nodes.lua @@ -0,0 +1,131 @@ +-- mobs/nodes.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +minetest.register_node("mobs:spawner", { + description = "I spawn things!", + drawtype = "airlike", + groups = {not_in_creative_inventory = 1}, + drop = "", + air_equivalent = true, + paramtype = "light", + inventory_image = "air.png", + floodable = true, + pointable = false, + sunlight_propagates = true, + walkable = false, + diggable = false, + buildable_to = true, + wield_image = "air.png", + on_blast = function() + end, + --[[ + on_destruct = function(pos) + print(dump(minetest.get_node_timer(pos))) + end, + --]] + on_timer = function(pos, elapsed) + if elapsed > 48 then + local immediate_surrounding = minetest.get_objects_inside_radius(pos, 1.12) + if #immediate_surrounding > 0 then + --print("Clear!") + return minetest.set_node(pos, {name = "air"}) + end + local surrounding = minetest.get_objects_inside_radius(pos, 16) + --print("There's " .. #surrounding .. "!") + if #surrounding > 6 then + local h = 0 + for i = 1, #surrounding do + local s = surrounding[i] + local sl = s:get_luaentity() + if sl and sl.health then + h = h + 1 + end + if s:is_player() then + h = h + 2 + --print("Player!") + end + end + --print(h .. "!") + if h > 3 then + --print("Clear!") + return minetest.set_node(pos, {name = "air"}) + end + end + local mob_pos = pos + if minetest.registered_nodes[minetest.get_node_or_nil(pos).name].walkable then + mob_pos.y = mob_pos.y + 1 + end + local mobs = { + "mobs:rat", + "mobs:npc", + } + local biome = minetest.get_biome_name(minetest.get_biome_data(pos).biome) + local tod = (minetest.get_timeofday() or 0) * 24000 + local night = tod > 19000 or tod < 06000 + local protection = minetest.find_node_near(mob_pos, 13, + {"protector:protect", "protector:protect2"}, true) + if not protection and (biome == "underground" or night) then + local mobs_to_insert = { + "mobs:dungeon_master", + "mobs:oerkki", + "mobs:zombie" .. math.random(4), + } + for i = 1, #mobs_to_insert do + mobs[#mobs + 1] = mobs_to_insert[i] + end + end + if biome ~= "underground" then + local mobs_to_insert = { + "mobs:sheep_white", + "mobs:kitten", + "mobs:bunny", + } + for i = 1, #mobs_to_insert do + mobs[#mobs + 1] = mobs_to_insert[i] + end + end + local mob = mobs[math.random(#mobs)] + minetest.add_entity(mob_pos, mob) + --print("Go " .. mob .. "!") + return minetest.set_node(pos, {name = "air"}) + else + --print("Go " .. math.floor(elapsed)) + minetest.get_node_timer(pos):set(elapsed + 1, elapsed) + end + end, +}) +minetest.register_abm({ + label = "Spawner Limiter", + nodenames = {"mobs:spawner"}, + --neighbors = {}, + interval = 1, + chance = 1, + catch_up = false, + action = function(pos, node, active_object_count, active_object_count_wider) + local i = active_object_count + local s = active_object_count_wider + local t = minetest.get_node_timer(pos) + if not t or not t:is_started() or + s > 2 or i > 1 then + local things = minetest.get_objects_inside_radius(pos, 16) + local ttl = 0 + for k, v in pairs(things) do + local h = v:get_luaentity() + if h and h.health and h.health > 0 then + ttl = ttl + 1 + end + local p = v:is_player() + if p then + ttl = ttl + 2 + end + end + if ttl > 4 then + --print("Clear " .. i .. " " .. s .. "!") + minetest.set_node(pos, {name = "air"}) + end + end + end, +}) +--minetest.register_lbm() +--minetest.register_on_mapgen() diff --git a/mods/mobs/npc.lua b/mods/mobs/npc.lua new file mode 100644 index 0000000..cdd234b --- /dev/null +++ b/mods/mobs/npc.lua @@ -0,0 +1,203 @@ +-- Mobs & NPC are part of Glitchtest game +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +-- NPC by TenPlus1 +-- Trader enhancements by jas + + +local S = mobs.intllib + +mobs.npc_drops = { + "default:pick_steel", "mobs:meat 2", "default:sword_steel", + "default:shovel_steel", "farming:bread", "bucket:bucket_water", + "walkie:talkie", "craftguide:book", "default:book", + "mobs:shears", "default:axe_steel", "default:diamond", + "default:papyrus", +} + +local function mob_detached_inv(self) + return { + allow_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return 0 + end, + allow_put = function(inv, listname, index, stack, player) + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + local name = player:get_player_name() + local detached = minetest.create_detached_inventory("trade_" .. self.tid, { + allow_put = function(inv, listname, index, stack, player) + if index ~= 2 then + return 0 + else + return stack:get_count() + end + end, + allow_move = function() + return 0 + end, + allow_take = function(inv, listname, index, stack, player) + return 0 + end, + on_put = function(p_inv, p_listname, p_index, p_stack, p_player) + local player_inv = p_player:get_inventory() + player_inv:add_item("main", p_inv:get_stack("exchange", 1)) + p_inv:set_list("exchange", {}) + minetest.close_formspec(name, "npc:npc_trade") + --[[ + if not self.owner or self.owner == "" then + self.object:get_luaentity().owner = p_player:get_player_name() + end + --]] + return -1, minetest.remove_detached_inventory("trade_" .. self.tid) + end, + }) + detached:set_size("exchange", 2 * 1) + detached:add_item("exchange", stack) + local trade_fs = "size[8,6.5]" .. + jas0.exit_button() .. + "label[0,0;I'll need something from you.]" .. + "list[detached:trade_" .. self.tid .. ";exchange;3,1;2,1]" .. + "list[current_player;main;0,2.5;8,1]" .. + "list[current_player;main;0,3.6;8,3;8]" .. + default.get_hotbar_bg(0, 2.5) .. + "" + inv:set_stack("trade", index, "") + local list = inv:get_list("trade") + for i = 1, #list do + list[i] = list[i]:to_string() + end + self.inv = minetest.serialize(list) + return 0, minetest.show_formspec(name, "npc:npc_trade", trade_fs) + end, + on_move = function(inv, from_list, from_index, to_list, to_index, count, player) + return 0 + end, + on_put = function(inv, listname, index, stack, player) + return 0 + end, + on_take = function(inv, listname, index, stack, player) + return 0 + end, + } +end + +mobs:register_mob("mobs:npc", { + type = "npc", + passive = false, + damage = 3, + attack_type = "dogfight", + attacks_monsters = true, + attack_npcs = false, + owner_loyal = true, + pathfinding = true, + hp_min = 20, + hp_max = 20, + armor = 100, + collisionbox = {-0.25, 0.0, -0.25, 0.25, 1.65 , 0.25}, + visual = "mesh", + mesh = "character.b3d", + drawtype = "front", + textures = { + {"mobs_npc.png"}, + {"mobs_npc2.png"}, -- female by nuttmeg20 + }, + child_texture = { + {"mobs_npc_baby.png"}, -- derpy baby by AmirDerAssassine + }, + makes_footstep_sound = true, + --sounds = {}, + walk_velocity = 1, + run_velocity = 2, + jump = true, + drops = { + {name = "shop:coin", chance = 1, min = 1, max = 6}, + {name = "shop:gold_ingot", chance = 2, min = 0, max = 2}, + {name = "shop:goldblock", chance = 3, min = 0, max = 1}, + }, + water_damage = 0, + lava_damage = 2, + light_damage = 0, + follow = {"farming:flour", "mobs:meat_raw", "default:gold_lump"}, + --view_range = 8, + owner = "", + order = "follow", + fear_height = 3, + animation = { + speed_normal = 30, + speed_run = 30, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 187, + run_start = 168, + run_end = 187, + punch_start = 200, + punch_end = 219, + }, + on_rightclick = function(self, clicker) + if mobs:feed_tame(self, clicker, 7, true, true) then + return + end + if mobs:capture_mob(self, clicker, 0, 5, 80, false, nil) then + return + end + if mobs:protect(self, clicker) then + return + end + + local item = clicker:get_wielded_item() + local name = clicker:get_player_name() + if not self.tid then + local tid = minetest.get_us_time() + local inv_id = minetest.create_detached_inventory("npc_" .. + tid, mob_detached_inv(self)) + inv_id:set_size("trade", 8 * 4) + for i = math.random(1, 2), #dresser.skins, 2 do + inv_id:add_item("trade", "dresser:skin_" .. dresser.skins[i][1]) + end + for i = math.random(1, 2), #mobs.npc_drops, 2 do + inv_id:add_item("trade", mobs.npc_drops[i]) + end + for i = math.random(1, 2), #dungeon_loot.registered_loot, 2 do + if dungeon_loot.registered_loot[i].chance > 0.2 then + inv_id:add_item("trade", dungeon_loot.registered_loot[i].name) + end + end + local inventory = inv_id:get_list("trade") + for i = 1, #inventory do + inventory[i] = inventory[i]:to_string() + end + self.inv = minetest.serialize(inventory) + self.tid = tid + else + local mob_inv = minetest.get_inventory({type = "detached", + name = "npc_" .. self.tid}) + if not mob_inv then + mob_inv = minetest.create_detached_inventory("npc_" .. + self.tid, mob_detached_inv(self)) + mob_inv:set_list("trade", minetest.deserialize(self.inv)) + end + end + self.order = "stand" + self.state = "stand" + minetest.after(0.1, function() + minetest.show_formspec(name, "mobs:npc", + "size[8,8.85]" .. + jas0.exit_button(-0.1, -0.075) .. + "label[0,0;What would you like?]" .. + "list[detached:npc_" .. self.tid .. ";trade;0,0.6.9;8,4]" .. + "list[current_player;main;0,4.79;8,1]" .. + "list[current_player;main;0,5.84;8,3;8]" .. + default.get_hotbar_bg(0, 4.79) .. + "") + end) + end, + --[[ + on_die = function(self, pos) + end, + --]] +}) + +mobs:register_egg("mobs:npc", "NPC", "default_brick.png", 1) diff --git a/mods/mobs/oerkki.lua b/mods/mobs/oerkki.lua new file mode 100644 index 0000000..4abbc04 --- /dev/null +++ b/mods/mobs/oerkki.lua @@ -0,0 +1,50 @@ +-- Oerkki by PilzAdam + +local S = mobs.intllib +mobs:register_mob("mobs:oerkki", { + type = "monster", + passive = false, + attack_type = "dogfight", + pathfinding = true, + reach = 2, + damage = 5, + hp_min = 5, + hp_max = 7, + armor = 100, + collisionbox = {-0.4, -1, -0.4, 0.4, 0.9, 0.4}, + visual = "mesh", + mesh = "mobs_oerkki.b3d", + textures = { + {"mobs_oerkki.png"}, + --{"mobs_oerkki2.png"}, + }, + makes_footstep_sound = false, + sounds = { + random = "mobs_oerkki", + }, + walk_velocity = 1, + run_velocity = 1, + --view_range = 10, + --jump = true, + drops = { + {name = "default:mese_crystal", chance = 2, min = 1, max = 2}, + {name = "default:obsidian", chance = 2, min = 0, max = 1}, + }, + water_damage = 7, + lava_damage = 4, + fear_height = 4, + animation = { + stand_start = 0, + stand_end = 23, + walk_start = 24, + walk_end = 36, + run_start = 37, + run_end = 49, + punch_start = 37, + punch_end = 49, + speed_normal = 15, + speed_run = 15, + }, +}) + +mobs:register_egg("mobs:oerkki", S("Oerkki"), "default_obsidian.png", 1) diff --git a/mods/mobs/rat.lua b/mods/mobs/rat.lua new file mode 100644 index 0000000..dba5d76 --- /dev/null +++ b/mods/mobs/rat.lua @@ -0,0 +1,39 @@ +-- Rat by PilzAdam + +local S = mobs.intllib +mobs:register_mob("mobs:rat", { + --stepheight = 0.6, + type = "animal", + passive = true, + hp_min = 1, + hp_max = 1, + armor = 200, + collisionbox = {-0.2, -1, -0.2, 0.2, -0.8, 0.2}, + visual = "mesh", + mesh = "mobs_rat.b3d", + textures = { + {"mobs_rat.png"}, + {"mobs_rat2.png"}, + }, + makes_footstep_sound = false, + sounds = { + random = "mobs_rat", + }, + walk_velocity = 1, + --run_velocity = 2, + runaway = false, + --jump_height = 6, + --jump = false, + drops = { + {name = "mobs:meat_raw", chance = 1, min = 1, max = 1}, + }, + water_damage = 0, + lava_damage = 4, + light_damage = 0, + fear_height = 2, + on_rightclick = function(self, clicker) + mobs:capture_mob(self, clicker, 50, 90, 100, true, "mobs:rat") + end, +}) + +mobs:register_egg("mobs:rat", S("Rat"), "mobs_rat_inventory.png", 0) diff --git a/mods/mobs/readme.MD b/mods/mobs/readme.MD new file mode 100644 index 0000000..5066d82 --- /dev/null +++ b/mods/mobs/readme.MD @@ -0,0 +1,83 @@ + +MOBS REDO for MINETEST + +Built from PilzAdam's original Simple Mobs with additional mobs by KrupnoPavel, Zeg9, ExeterDad and AspireMint. + + +This mod contains the API only for adding your own mobs into the world, so please use the additional modpacks to add animals, monsters etc. + + +https://forum.minetest.net/viewtopic.php?f=11&t=9917 + + +Crafts: + + - Nametag (paper, black dye, string) can be used right-click on a tamed mob to give them a name. + - Nets can be used to right-click tamed mobs to pick them up and place inside inventory as a spawn egg. + - Magic Lasso is similar to nets but with a better chance of picking up larger mobs. + - Shears are used to right-click sheep and return 1-3 wool. + - Protection Rune lets you protect tamed mobs from harm by other players + - Mob Fence and Fence Top (to stop mobs escaping/glitching through fences) + +Lucky Blocks: 9 + + +Changelog: +- 1.47- Mob damage changes, min and max light level for damage added, ignition sources checked for lava damage +- 1.46- Mobs only drop rare items when killed by player (drops.min = 0 makes them rare), code tweak, pathfinding no longer sees through walkable nodes +- 1.45- Added Fence Top to add on top of any fence to stop mobs escaping, new line_of_sight tweaked by Astrobe +- 1.44- Added ToolRanks support for swords when attacking mobs +- 1.43- Better 0.4.16 compatibility, added general attack function and settings +- 1.42- Added "all" option to immune_to table, tidied floating mobs to be less intensive +- 1.41- Mob pathfinding has been updated thanks to Elkien3 +- 1.40- Updated to use newer functions, requires Minetest 0.4.16+ to work. +- 1.39- Added 'on_breed', 'on_grown' and 'do_punch' custom functions per mob +- 1.38- Better entity checking, nametag setting and on_spawn function added to mob registry, tweaked light damage +- 1.37- Added support for Raymoo's CMI (common mob interface) mod: https://forum.minetest.net/viewtopic.php?f=9&t=15448 +- 1.36- Death check added, if mob dies in fire/lava/with lava pick then drops are cooked +- 1.35- Added owner_loyal flag for owned mobs to attack player enemies, also fixed group_attack +- 1.34- Added function to fly mob using directional movement (thanks D00Med for flying code) +- 1.33- Added functions to mount ride mobs (mobs.attach, mobs.detach, mobs.drive) many thanks to Blert2112 +- 1.32- Added new spawn check to count specific mobs AND new minetest.conf setting to chance spawn chance and numbers, added ability to protect tamed mobs +- 1.31- Added 'attack_animals' and 'specific_attack' flags for custom monster attacks, also 'mob_difficulty' .conf setting to make mobs harder. +- 1.30- Added support for invisibility mod (mobs cant attack what they cant see), tweaked and tidied code +- 1.29- Split original Mobs Redo into a modpack to make it easier to disable mob sets (animal, monster, npc) or simply use the Api itself for your own mod +- 1.28- New damage system added with ability for mob to be immune to weapons or healed by them :) +- 1.27- Added new sheep, lava flan and spawn egg textures. New Lava Pick tool smelts what you dig. New atan checking function. +- 1.26- Pathfinding feature added thanks to rnd, when monsters attack they become scary smart in finding you :) also, beehive produces honey now :) +- 1.25- Mobs no longer spawn within 12 blocks of player or despawn within same range, spawners now have player detection, Code tidy and tweak. +- 1.24- Added feature where certain animals run away when punched (runaway = true in mob definition) +- 1.23- Added mob spawner block for admin to setup spawners in-game (place and right click to enter settings) +- 1.22- Added ability to name tamed animals and npc using nametags, also npc will attack anyone who punches them apart from owner +- 1.21- Added some more error checking to reduce serialize.h error and added height checks for falling off cliffs (thanks cmdskp) +- 1.20- Error checking added to remove bad mobs, out of map limit mobs and stop serialize.h error +- 1.19- Chickens now drop egg items instead of placing the egg, also throwing eggs result in 1/8 chance of spawning chick +- 1.18- Added docile_by_day flag so that monsters will not attack automatically during daylight hours unless hit first +- 1.17- Added 'dogshoot' attack type, shoots when out of reach, melee attack when in reach, also api tweaks and self.reach added +- 1.16- Mobs follow multiple items now, Npc's can breed +- 1.15- Added Feeding/Taming/Breeding function, right-click to pick up any sheep with X mark on them and replace with new one to fix compatibility. +- 1.14- All .self variables saved in staticdata, Fixed self.health bug +- 1.13- Added capture function (thanks blert2112) chance of picking up mob with hand; net; magic lasso, replaced some .x models with newer .b3d one's +- 1.12- Added animal ownership so that players cannot steal your tamed animals +- 1.11- Added flying mobs (and swimming), fly=true and fly_in="air" or "deafult:water_source" for fishy +- 1,10- Footstep removed (use replace), explosion routine added for exploding mobs. +- 1.09- reworked breeding routine, added mob rotation value, added footstep feature, added jumping mobs with sounds feature, added magic lasso for picking up animals +- 1.08- Mob throwing attack has been rehauled so that they can damage one another, also drops and on_die function added +- 1.07- Npc's can now be set to follow player or stand by using self.order and self.owner variables +- beta- Npc mob added, kills monsters, attacks player when punched, right click with food to heal or gold lump for drop +- 1.06- Changed recovery times after breeding, and time taken to grow up (can be sped up by feeding baby animal) +- 1.05- Added ExeterDad's bunny's which can be picked up and tamed with 4 carrots from farming redo or farming_plus, also shears added to get wool from sheep and lastly Jordach/BSD's kitten +- 1.04- Added mating for sheep, cows and hogs... feed animals to make horny and hope for a baby which is half size, will grow up quick though :) +- 1.03- Added mob drop/replace feature so that chickens can drop eggs, cow/sheep can eat grass/wheat etc. +- 1.02- Sheared sheep are remembered and spawn shaven, Warthogs will attack when threatened, Api additions +- 1.01- Mobs that suffer fall damage or die in water/lava/sunlight will now drop items +- 1.0 - more work on Api so that certain mobs can float in water while some sink like a brick :) +- 0.9 - Spawn eggs added for all mobs (admin only, cannot be placed in protected areas)... Api tweaked +- 0.8 - Added sounds to monster mobs (thanks Cyberpangolin for the sfx) and also chicken sound +- 0.7 - mobs.protected switch added to api.lua, when set to 1 mobs no longer spawn in protected areas, also bug fixes +- 0.6 - Api now supports multi-textured mobs, e.g oerkki, dungeon master, rats and chickens have random skins when spawning (sheep fix TODO), also new Honey block +- 0.5 - Mobs now float in water, die from falling, and some code improvements +- 0.4 - Dungeon Masters and Mese Monsters have much better aim due to shoot_offset, also they can both shoot through nodes that aren't walkable (flowers, grass etc) plus new sheep sound :) +- 0.3 - Added LOTT's Spider mob, made Cobwebs, added KPavel's Bee with Honey and Beehives (made texture), Warthogs now have sound and can be tamed, taming of shaved sheep or milked cow with 8 wheat so it will not despawn, many bug fixes :) +- 0.2 - Cooking bucket of milk into cheese now returns empty bucket +- 0.1 - Initial Release diff --git a/mods/mobs/settingtypes.txt b/mods/mobs/settingtypes.txt new file mode 100644 index 0000000..0821437 --- /dev/null +++ b/mods/mobs/settingtypes.txt @@ -0,0 +1,29 @@ +# If false then mobs no longer spawn in world without spawner or spawn egg +mobs_spawn (Spawn Mobs) bool true + +# If enabled then monsters no longer spawn in world +only_peaceful_mobs (Only spawn peaceful Mobs) bool false + +# If enabled then punching mobs no longer shows blood effects +mobs_disable_blood (Disable Mob blood) bool false + +# If disabled then Mobs no longer destroy world blocks +mobs_griefing (Griefing Mobs) bool true + +# If false then Mobs no longer spawn inside player protected areas +mobs_spawn_protected (Spawn Mobs in protected areas) bool true + +# If true Mobs will be removed once a map chunk is out of view +remove_far_mobs (Remove far Mobs) bool true + +# Sets Mob difficulty level by multiplying punch damage +mob_difficulty (Mob difficulty) float 1.0 + +# If disabled health status no longer appears above Mob when punched +mob_show_health (Show Mob health) bool true + +# Contains a value used to multiply Mob spawn values +mob_chance_multiplier (Mob chance multiplier) float 1.0 + +# When false Mob no longer drop items when killed +mobs_drop_items (Mob drops) bool true diff --git a/mods/mobs/sheep.lua b/mods/mobs/sheep.lua new file mode 100644 index 0000000..634b703 --- /dev/null +++ b/mods/mobs/sheep.lua @@ -0,0 +1,171 @@ +-- mobs/sheep.lua is part of Glitchtest +-- Copyright 2018 James Stevenson +-- GNU GPL 3 + +-- Sheep by PilzAdam, texture converted to minetest by AMMOnym from Summerfield pack +local S = mobs.intllib +local all_colours = { + {"black", S("Black"), "#000000b0"}, + {"blue", S("Blue"), "#015dbb70"}, + {"brown", S("Brown"), "#663300a0"}, + {"cyan", S("Cyan"), "#01ffd870"}, + {"dark_green", S("Dark Green"), "#005b0770"}, + {"dark_grey", S("Dark Grey"), "#303030b0"}, + {"green", S("Green"), "#61ff0170"}, + {"grey", S("Grey"), "#5b5b5bb0"}, + {"magenta", S("Magenta"), "#ff05bb70"}, + {"orange", S("Orange"), "#ff840170"}, + {"pink", S("Pink"), "#ff65b570"}, + {"red", S("Red"), "#ff0000a0"}, + {"violet", S("Violet"), "#2000c970"}, + {"white", S("White"), "#abababc0"}, + {"yellow", S("Yellow"), "#e3ff0070"}, +} + +for _, col in ipairs(all_colours) do + mobs:register_mob("mobs:sheep_"..col[1], { + --stepheight = 0.6, + type = "animal", + passive = true, + hp_min = 5, + hp_max = 10, + armor = 100, + collisionbox = {-0.5, -1, -0.5, 0.5, 0.3, 0.5}, + visual = "mesh", + mesh = "mobs_sheep.b3d", + textures = { + {"mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" .. + col[3] .. ")"}, + }, + gotten_texture = {"mobs_sheep_shaved.png"}, + gotten_mesh = "mobs_sheep_shaved.b3d", + makes_footstep_sound = true, + sounds = { + gain = (math.random(60, 93) / 100 + math.random() / 11) / 3, + distance = 24, + random = "mobs_sheep", + damage = "mobs_sheep", + death = "mobs_sheep", + war_cry = "mobs_sheep", + attack = "mobs_sheep", + shoot_attack = "mobs_sheep", + fuse = "mobs_sheep", + explode = "mobs_sheep", + }, + walk_velocity = 1, + run_velocity = 2, + runaway = true, + --jump = true, + --jump_height = 6, + pushable = true, + drops = { + {name = "mobs:meat_raw", chance = 1, min = 1, max = 2}, + }, + water_damage = 1, + lava_damage = 5, + light_damage = 0, + glow = 1, + animation = { + speed_normal = 15, + speed_run = 15, + stand_start = 0, + stand_end = 80, + walk_start = 81, + walk_end = 100, + }, + follow = {"farming:wheat", "default:grass_5"}, + --view_range = 8, + --replace_rate = 10, + --replace_what = {"default:grass_3", "default:grass_4", "default:grass_5", "farming:wheat_8"}, + --replace_with = "air", + --replace_offset = -1, + fear_height = 3, + on_rightclick = function(self, clicker) + -- Sound the alarm! + if not self.clicked then + local gain = math.random(60, 93) / 100 + math.random() / 11 + local pitch = 0.96 + math.random(1, 7) / 100 + math.random() / 11 + local sh = minetest.sound_play("mobs_sheep", { + gain = gain, + pitch = pitch, + object = self.object, + max_hear_distance = 128, + }) + minetest.after(0.35, minetest.sound_fade, sh, -1, 0.0) + self.clicked = true + else + self.clicked = false + end + --are we feeding? + if mobs:feed_tame(self, clicker, 8, true, true) then + --if full grow fuzz + if self.gotten == false then + self.object:set_properties({ + textures = {"mobs_sheep_base.png^(mobs_sheep_wool.png^[colorize:" .. col[3] .. ")"}, + mesh = "mobs_sheep.b3d", + }) + end + + return + end + local item = clicker:get_wielded_item() + local itemname = item:get_name() + local name = clicker:get_player_name() + --are we giving a haircut> + if itemname == "mobs:shears" then + if self.gotten ~= false or self.child ~= false then + return + end + self.gotten = true -- shaved + local obj = minetest.add_item( + self.object:get_pos(), + ItemStack( "wool:" .. col[1] .. " " .. math.random(1, 3) ) + ) + if obj then + obj:setvelocity({ + x = math.random(-1, 1), + y = 5, + z = math.random(-1, 1) + }) + end + item:add_wear(650) -- 100 uses + clicker:set_wielded_item(item) + self.object:set_properties({ + textures = {"mobs_sheep_shaved.png"}, + mesh = "mobs_sheep_shaved.b3d", + }) + return + end + if itemname:find("dye:") then + if self.gotten == false and + self.child == false and + self.tamed == true and + name == self.owner then + local colr = string.split(itemname, ":")[2] + for _, c in pairs(all_colours) do + if c[1] == colr then + local pos = self.object:get_pos() + self.object:remove() + local mob = minetest.add_entity(pos, "mobs:sheep_" .. colr) + local ent = mob:get_luaentity() + ent.owner = name + ent.tamed = true + -- take item + if not mobs.is_creative(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + break + end + end + end + return + end + -- protect mod with mobs:protector item + if mobs:protect(self, clicker) then return end + --are we capturing? + if mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) then return end + end + }) + mobs:register_egg("mobs:sheep_"..col[1], S("@1 Sheep", col[2]), "wool_"..col[1]..".png", 1) +end diff --git a/mods/mobs/sounds/mobs_dungeonmaster.ogg b/mods/mobs/sounds/mobs_dungeonmaster.ogg new file mode 100644 index 0000000..4ac5f4a Binary files /dev/null and b/mods/mobs/sounds/mobs_dungeonmaster.ogg differ diff --git a/mods/mobs/sounds/mobs_fireball.ogg b/mods/mobs/sounds/mobs_fireball.ogg new file mode 100644 index 0000000..bdc4ac2 Binary files /dev/null and b/mods/mobs/sounds/mobs_fireball.ogg differ diff --git a/mods/mobs/sounds/mobs_kitten.ogg b/mods/mobs/sounds/mobs_kitten.ogg new file mode 100644 index 0000000..688eff7 Binary files /dev/null and b/mods/mobs/sounds/mobs_kitten.ogg differ diff --git a/mods/mobs/sounds/mobs_oerkki.ogg b/mods/mobs/sounds/mobs_oerkki.ogg new file mode 100644 index 0000000..aac6e43 Binary files /dev/null and b/mods/mobs/sounds/mobs_oerkki.ogg differ diff --git a/mods/mobs/sounds/mobs_punch.ogg b/mods/mobs/sounds/mobs_punch.ogg new file mode 100644 index 0000000..28a500b Binary files /dev/null and b/mods/mobs/sounds/mobs_punch.ogg differ diff --git a/mods/mobs/sounds/mobs_rat.1.ogg b/mods/mobs/sounds/mobs_rat.1.ogg new file mode 100644 index 0000000..43e1126 Binary files /dev/null and b/mods/mobs/sounds/mobs_rat.1.ogg differ diff --git a/mods/mobs/sounds/mobs_rat.2.ogg b/mods/mobs/sounds/mobs_rat.2.ogg new file mode 100644 index 0000000..f848df7 Binary files /dev/null and b/mods/mobs/sounds/mobs_rat.2.ogg differ diff --git a/mods/mobs/sounds/mobs_sheep.1.ogg b/mods/mobs/sounds/mobs_sheep.1.ogg new file mode 100644 index 0000000..82dce69 Binary files /dev/null and b/mods/mobs/sounds/mobs_sheep.1.ogg differ diff --git a/mods/mobs/sounds/mobs_sheep.2.ogg b/mods/mobs/sounds/mobs_sheep.2.ogg new file mode 100644 index 0000000..471d9cb Binary files /dev/null and b/mods/mobs/sounds/mobs_sheep.2.ogg differ diff --git a/mods/mobs/sounds/mobs_spell.ogg b/mods/mobs/sounds/mobs_spell.ogg new file mode 100644 index 0000000..455b54f Binary files /dev/null and b/mods/mobs/sounds/mobs_spell.ogg differ diff --git a/mods/mobs/sounds/mobs_swing.ogg b/mods/mobs/sounds/mobs_swing.ogg new file mode 100644 index 0000000..ffe6a9c Binary files /dev/null and b/mods/mobs/sounds/mobs_swing.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.1.ogg b/mods/mobs/sounds/mobs_zombie.1.ogg new file mode 100644 index 0000000..9e0a7cd Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.1.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.2.ogg b/mods/mobs/sounds/mobs_zombie.2.ogg new file mode 100644 index 0000000..1f92204 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.2.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.3.ogg b/mods/mobs/sounds/mobs_zombie.3.ogg new file mode 100644 index 0000000..1c60aec Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.3.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.4.ogg b/mods/mobs/sounds/mobs_zombie.4.ogg new file mode 100644 index 0000000..8eee5e0 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.4.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.5.ogg b/mods/mobs/sounds/mobs_zombie.5.ogg new file mode 100644 index 0000000..c4defd4 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.5.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie.6.ogg b/mods/mobs/sounds/mobs_zombie.6.ogg new file mode 100644 index 0000000..9aa4824 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie.6.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie_death.ogg b/mods/mobs/sounds/mobs_zombie_death.ogg new file mode 100644 index 0000000..d873875 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie_death.ogg differ diff --git a/mods/mobs/sounds/mobs_zombie_hit.ogg b/mods/mobs/sounds/mobs_zombie_hit.ogg new file mode 100644 index 0000000..5c7c5e1 Binary files /dev/null and b/mods/mobs/sounds/mobs_zombie_hit.ogg differ diff --git a/mods/mobs/textures/mobs_blood.png b/mods/mobs/textures/mobs_blood.png new file mode 100644 index 0000000..77cfbda Binary files /dev/null and b/mods/mobs/textures/mobs_blood.png differ diff --git a/mods/mobs/textures/mobs_bunny_brown.png b/mods/mobs/textures/mobs_bunny_brown.png new file mode 100644 index 0000000..3a71d94 Binary files /dev/null and b/mods/mobs/textures/mobs_bunny_brown.png differ diff --git a/mods/mobs/textures/mobs_bunny_evil.png b/mods/mobs/textures/mobs_bunny_evil.png new file mode 100644 index 0000000..683170d Binary files /dev/null and b/mods/mobs/textures/mobs_bunny_evil.png differ diff --git a/mods/mobs/textures/mobs_bunny_grey.png b/mods/mobs/textures/mobs_bunny_grey.png new file mode 100644 index 0000000..d41d6c1 Binary files /dev/null and b/mods/mobs/textures/mobs_bunny_grey.png differ diff --git a/mods/mobs/textures/mobs_bunny_inv.png b/mods/mobs/textures/mobs_bunny_inv.png new file mode 100644 index 0000000..762b713 Binary files /dev/null and b/mods/mobs/textures/mobs_bunny_inv.png differ diff --git a/mods/mobs/textures/mobs_bunny_white.png b/mods/mobs/textures/mobs_bunny_white.png new file mode 100644 index 0000000..0445e88 Binary files /dev/null and b/mods/mobs/textures/mobs_bunny_white.png differ diff --git a/mods/mobs/textures/mobs_chicken_egg.png b/mods/mobs/textures/mobs_chicken_egg.png new file mode 100644 index 0000000..be8a4e1 Binary files /dev/null and b/mods/mobs/textures/mobs_chicken_egg.png differ diff --git a/mods/mobs/textures/mobs_chicken_egg_overlay.png b/mods/mobs/textures/mobs_chicken_egg_overlay.png new file mode 100644 index 0000000..e81716a Binary files /dev/null and b/mods/mobs/textures/mobs_chicken_egg_overlay.png differ diff --git a/mods/mobs/textures/mobs_dungeon_master.png b/mods/mobs/textures/mobs_dungeon_master.png new file mode 100644 index 0000000..dbc9584 Binary files /dev/null and b/mods/mobs/textures/mobs_dungeon_master.png differ diff --git a/mods/mobs/textures/mobs_dungeon_master2.png b/mods/mobs/textures/mobs_dungeon_master2.png new file mode 100644 index 0000000..53100ab Binary files /dev/null and b/mods/mobs/textures/mobs_dungeon_master2.png differ diff --git a/mods/mobs/textures/mobs_dungeon_master3.png b/mods/mobs/textures/mobs_dungeon_master3.png new file mode 100644 index 0000000..4bf8d66 Binary files /dev/null and b/mods/mobs/textures/mobs_dungeon_master3.png differ diff --git a/mods/mobs/textures/mobs_fireball.png b/mods/mobs/textures/mobs_fireball.png new file mode 100644 index 0000000..d896563 Binary files /dev/null and b/mods/mobs/textures/mobs_fireball.png differ diff --git a/mods/mobs/textures/mobs_kitten_ginger.png b/mods/mobs/textures/mobs_kitten_ginger.png new file mode 100644 index 0000000..1707c2e Binary files /dev/null and b/mods/mobs/textures/mobs_kitten_ginger.png differ diff --git a/mods/mobs/textures/mobs_kitten_inv.png b/mods/mobs/textures/mobs_kitten_inv.png new file mode 100644 index 0000000..6afa61f Binary files /dev/null and b/mods/mobs/textures/mobs_kitten_inv.png differ diff --git a/mods/mobs/textures/mobs_kitten_sandy.png b/mods/mobs/textures/mobs_kitten_sandy.png new file mode 100644 index 0000000..052f04e Binary files /dev/null and b/mods/mobs/textures/mobs_kitten_sandy.png differ diff --git a/mods/mobs/textures/mobs_kitten_splotchy.png b/mods/mobs/textures/mobs_kitten_splotchy.png new file mode 100644 index 0000000..1fad994 Binary files /dev/null and b/mods/mobs/textures/mobs_kitten_splotchy.png differ diff --git a/mods/mobs/textures/mobs_kitten_striped.png b/mods/mobs/textures/mobs_kitten_striped.png new file mode 100644 index 0000000..4d1a0cc Binary files /dev/null and b/mods/mobs/textures/mobs_kitten_striped.png differ diff --git a/mods/mobs/textures/mobs_leather.png b/mods/mobs/textures/mobs_leather.png new file mode 100644 index 0000000..3205e5d Binary files /dev/null and b/mods/mobs/textures/mobs_leather.png differ diff --git a/mods/mobs/textures/mobs_meat.png b/mods/mobs/textures/mobs_meat.png new file mode 100644 index 0000000..4c63fdd Binary files /dev/null and b/mods/mobs/textures/mobs_meat.png differ diff --git a/mods/mobs/textures/mobs_meat_raw.png b/mods/mobs/textures/mobs_meat_raw.png new file mode 100644 index 0000000..0dea4ec Binary files /dev/null and b/mods/mobs/textures/mobs_meat_raw.png differ diff --git a/mods/mobs/textures/mobs_nametag.png b/mods/mobs/textures/mobs_nametag.png new file mode 100644 index 0000000..74005b3 Binary files /dev/null and b/mods/mobs/textures/mobs_nametag.png differ diff --git a/mods/mobs/textures/mobs_npc.png b/mods/mobs/textures/mobs_npc.png new file mode 100644 index 0000000..9356398 Binary files /dev/null and b/mods/mobs/textures/mobs_npc.png differ diff --git a/mods/mobs/textures/mobs_npc2.png b/mods/mobs/textures/mobs_npc2.png new file mode 100644 index 0000000..a9d1a2c Binary files /dev/null and b/mods/mobs/textures/mobs_npc2.png differ diff --git a/mods/mobs/textures/mobs_npc_baby.png b/mods/mobs/textures/mobs_npc_baby.png new file mode 100644 index 0000000..e26e450 Binary files /dev/null and b/mods/mobs/textures/mobs_npc_baby.png differ diff --git a/mods/mobs/textures/mobs_oerkki.png b/mods/mobs/textures/mobs_oerkki.png new file mode 100644 index 0000000..a2791fa Binary files /dev/null and b/mods/mobs/textures/mobs_oerkki.png differ diff --git a/mods/mobs/textures/mobs_oerkki2.png b/mods/mobs/textures/mobs_oerkki2.png new file mode 100644 index 0000000..1e74f0c Binary files /dev/null and b/mods/mobs/textures/mobs_oerkki2.png differ diff --git a/mods/mobs/textures/mobs_rat.png b/mods/mobs/textures/mobs_rat.png new file mode 100644 index 0000000..f83da08 Binary files /dev/null and b/mods/mobs/textures/mobs_rat.png differ diff --git a/mods/mobs/textures/mobs_rat2.png b/mods/mobs/textures/mobs_rat2.png new file mode 100644 index 0000000..a8670df Binary files /dev/null and b/mods/mobs/textures/mobs_rat2.png differ diff --git a/mods/mobs/textures/mobs_rat_inventory.png b/mods/mobs/textures/mobs_rat_inventory.png new file mode 100644 index 0000000..a8d6151 Binary files /dev/null and b/mods/mobs/textures/mobs_rat_inventory.png differ diff --git a/mods/mobs/textures/mobs_rotten_flesh.png b/mods/mobs/textures/mobs_rotten_flesh.png new file mode 100644 index 0000000..e25c833 Binary files /dev/null and b/mods/mobs/textures/mobs_rotten_flesh.png differ diff --git a/mods/mobs/textures/mobs_shears.png b/mods/mobs/textures/mobs_shears.png new file mode 100644 index 0000000..aa16f2e Binary files /dev/null and b/mods/mobs/textures/mobs_shears.png differ diff --git a/mods/mobs/textures/mobs_sheep_base.png b/mods/mobs/textures/mobs_sheep_base.png new file mode 100644 index 0000000..c3c2c4a Binary files /dev/null and b/mods/mobs/textures/mobs_sheep_base.png differ diff --git a/mods/mobs/textures/mobs_sheep_shaved.png b/mods/mobs/textures/mobs_sheep_shaved.png new file mode 100644 index 0000000..e9023a4 Binary files /dev/null and b/mods/mobs/textures/mobs_sheep_shaved.png differ diff --git a/mods/mobs/textures/mobs_sheep_wool.png b/mods/mobs/textures/mobs_sheep_wool.png new file mode 100644 index 0000000..2dca0dc Binary files /dev/null and b/mods/mobs/textures/mobs_sheep_wool.png differ diff --git a/mods/mobs/textures/mobs_zombie.png b/mods/mobs/textures/mobs_zombie.png new file mode 100644 index 0000000..6f0c018 Binary files /dev/null and b/mods/mobs/textures/mobs_zombie.png differ diff --git a/mods/mobs/textures/mobs_zombie_head.png b/mods/mobs/textures/mobs_zombie_head.png new file mode 100644 index 0000000..bd628a7 Binary files /dev/null and b/mods/mobs/textures/mobs_zombie_head.png differ diff --git a/mods/mobs/zombies.lua b/mods/mobs/zombies.lua new file mode 100644 index 0000000..ab52e31 --- /dev/null +++ b/mods/mobs/zombies.lua @@ -0,0 +1,213 @@ +-- Zombie by BlockMen +mobs:register_mob("mobs:zombie1", { + type = "monster", + passive = false, + attack_type = "dogfight", + reach = 2, + damage = 6, + hp_min = 15, + hp_max = 16, + armor = 97, + collisionbox = {-0.25, -1, -0.3, 0.25, 0.75, 0.3}, + visual = "mesh", + mesh = "creatures_mob.x", + textures = { + {"mobs_zombie.png"}, + }, + makes_footstep_sound = true, + sounds = { + random = "mobs_zombie", + damage = "mobs_zombie_hit", + attack = "groan", + death = "mobs_zombie_death", + }, + walk_velocity = 0.25, + run_velocity = 0.25, + jump = true, + floats = 0, + drops = { + {name = "mobs:rotten_flesh", + chance = 1, min = 1, max = 2,}, + {name = "shop:coin", + chance = 1, min = 1, max = 2,}, + {name = "default:gold_ingot", + chance = 2, min = 0, max = 1,}, + }, + water_damage = 0, + lava_damage = 1, + light_damage = 0, + fall_damage = 2, + animation = { + speed_normal = 5, + speed_run = 5, + stand_start = 0, + stand_end = 79, + walk_start = 168, + walk_end = 188, + run_start = 168, + run_end = 188, + --punch_start = 168, + --punch_end = 188, + }, +}) + +-- 1 Arm +mobs:register_mob("mobs:zombie2", { + type = "monster", + passive = false, + attack_type = "dogfight", + reach = 2, + damage = 6, + hp_min = 20, + hp_max = 20, + armor = 100, + collisionbox = {-0.4, -1, -0.4, 0.4, 0.8, 0.4}, + visual = "mesh", + mesh = "zombie_one-arm.b3d", + textures = { + {"mobs_zombie.png"} + }, + makes_footstep_sound = true, + sounds = { + random = "mobs_zombie", + damage = "mobs_zombie_hit", + attack = "groan", + death = "mobs_zombie_death", + }, + walk_velocity = 0.5, + run_velocity = 0.5, + jump = true, + floats = 0, + drops = { + {name = "mobs:rotten_flesh", + chance = 1, min = 1, max = 2,}, + {name = "shop:coin", + chance = 1, min = 1, max = 2,}, + {name = "default:gold_ingot", + chance = 2, min = 0, max = 1,}, + }, + lava_damage = 5, + light_damage = 0, + fall_damage = 2, + animation = { + speed_normal = 5, + speed_run = 5, + punch_speed = 20, + walk_start = 0, + walk_end = 20, + run_start = 0, + run_end = 20, + punch_start = 21, + punch_end = 51, + }, +}) + +-- Crawler +mobs:register_mob("mobs:zombie3", { + type = "monster", + passive = false, + attack_type = "dogfight", + reach = 2, + damage = 6, + hp_min = 20, + hp_max = 20, + armor = 100, + collisionbox = {-0.5, -.5, -0.4, 0.5, 0.2, 0.4}, + visual = "mesh", + mesh = "zombie_crawler.b3d", + textures = { + {"mobs_zombie.png"} + }, + makes_footstep_sound = true, + sounds = { + random = "mobs_zombie", + damage = "mobs_zombie_hit", + attack = "groan", + death = "mobs_zombie_death", + }, + walk_velocity = 0.1, + run_velocity = 0.1, + jump = true, + floats = 0, + drops = { + {name = "mobs:rotten_flesh", + chance = 1, min = 1, max = 2,}, + {name = "shop:coin", + chance = 1, min = 1, max = 2,}, + {name = "default:gold_ingot", + chance = 2, min = 0, max = 1,}, + }, + lava_damage = 5, + light_damage = 0, + fall_damage = 2, + animation = { + speed_normal = 10, + speed_run = 10, + punch_speed = 60, + walk_start = 0, + walk_end = 40, + run_start = 0, + run_end = 40, + punch_start = 41, + punch_end = 71, + }, +}) + +-- Normal +mobs:register_mob("mobs:zombie4", { + type = "monster", + passive = false, + attack_type = "dogfight", + reach = 2, + damage = 6, + hp_min = 12, + hp_max = 12, + armor = 100, + collisionbox = {-0.4, -1, -0.4, 0.4, 0.8, 0.4}, + visual = "mesh", + mesh = "zombie_normal.b3d", + textures = { + {"mobs_zombie.png"} + }, + makes_footstep_sound = true, + sounds = { + random = "mobs_zombie", + damage = "mobs_zombie_hit", + attack = "groan", + death = "mobs_zombie_death", + }, + walk_velocity = 0.25, + run_velocity = 0.75, + jump = true, + floats = 0, + drops = { + {name = "mobs:rotten_flesh", + chance = 1, min = 1, max = 2,}, + {name = "shop:coin", + chance = 1, min = 1, max = 2,}, + {name = "default:gold_ingot", + chance = 2, min = 0, max = 1,}, + }, + lava_damage = 5, + light_damage = 0, + fall_damage = 2, + animation = { + speed_normal = 20, + speed_run = 20, + punch_speed = 20, + stand_start = 0, + stand_end = 40, + walk_start = 41, + walk_end = 101, + run_start = 41, + run_end = 101, + punch_start = 102, + punch_end = 142, + }, +}) + +-- Eggs +mobs:register_egg("mobs:zombie1", "Original Zombie", "mobs_zombie_head.png", 0) +mobs:register_egg("mobs:zombie2", "One Armed Zombie", "mobs_zombie_head.png", 0) +mobs:register_egg("mobs:zombie3", "Crawling Zombie", "mobs_zombie_head.png", 0) +mobs:register_egg("mobs:zombie4", "New Zombie", "mobs_zombie_head.png", 0) diff --git a/mods/multiskin/LICENSE b/mods/multiskin/LICENSE new file mode 100644 index 0000000..8864d4a --- /dev/null +++ b/mods/multiskin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mods/multiskin/README.md b/mods/multiskin/README.md new file mode 100644 index 0000000..a92a724 --- /dev/null +++ b/mods/multiskin/README.md @@ -0,0 +1,51 @@ +[mod] Multiskin [multiskin] [0.1.1] +=================================== + +**Minetest Version:** 0.4.16 + +**Depends:** default + +Adds per-player support for version 1.8 minecraft skins. + +On its own this mod acts as a replacement for the out-dated player_textures +mod by PilzAdam. Individual player textures can be placed in the mod's +textures directory and will be automatically assigned to a player by naming +the texture file as `player_.png` + +This mod also supports the following skin-switching mods which can be used +in conjuction with the multiskin default skins and chat commands. +``` +[mod] Skins [skins] by Zeg9 +[mod] Simple Skins [simple_skins] by TenPlus1 +[mod] Unified Skins [u_skins] by SmallJoker +[mod] Wardrobe [wardrobe] by prestidigitator +``` +Note that auto skin format detection is only available for these mods if +the multiskin mod is listed in the `secure.trusted_mods` setting. + +Configuration +------------- + +You can set the default skin by including the following settings in your +minetest.conf + +Supported formats are `1.0` and `1.8` +``` +multiskin_skin = +multiskin_format = +``` +Chat Commands +------------- + +Requires `server` priv in multiplayer mode, no privs required in singleplayer. +``` +/multiskin format +/multiskin set +/multiskin unset +/multiskin help +``` +TODO +---- + +Document the api and add support to my 3d_armor and clothing mods. + diff --git a/mods/multiskin/depends.txt b/mods/multiskin/depends.txt new file mode 100644 index 0000000..13f19e4 --- /dev/null +++ b/mods/multiskin/depends.txt @@ -0,0 +1,2 @@ +default +sfinv? diff --git a/mods/multiskin/description.txt b/mods/multiskin/description.txt new file mode 100644 index 0000000..d905ff7 --- /dev/null +++ b/mods/multiskin/description.txt @@ -0,0 +1,2 @@ +Dual skin format player model. +Supports minecraft 1.0 and 1.8 skin formats on a per-player basis. diff --git a/mods/multiskin/init.lua b/mods/multiskin/init.lua new file mode 100644 index 0000000..fa2984d --- /dev/null +++ b/mods/multiskin/init.lua @@ -0,0 +1,311 @@ +local modname = minetest.get_current_modname() +local modpath = minetest.get_modpath(modname) +local dir_list = minetest.get_dir_list(modpath.."/textures") +local birthday_suit = {"multiskin_female.png", "multiskin_male.png"} +local default_skin = function(player) + if player and player:get_meta():get_string("gender") == "male" then + return birthday_suit[2] + elseif player and player:get_meta():get_string("gender") == "female" then + return birthday_suit[1] + else + local gender = birthday_suit[math.random(2)] + if player then + player:get_meta():set_string("gender", gender:sub(11, -5)) + end + return gender + end +end +local default_format = minetest.setting_get("multiskin_format") or "1.0" +local player_skins = {} +local player_format = {} +local player_textures = {} +local skin_previews = {} +local skin_format = {[default_skin()]=default_format} + +local function get_skin_format(file) + file:seek("set", 1) + if file:read(3) == "PNG" then + file:seek("set", 16) + local ws = file:read(4) + local hs = file:read(4) + local w = ws:sub(3, 3):byte() * 256 + ws:sub(4, 4):byte() + local h = hs:sub(3, 3):byte() * 256 + hs:sub(4, 4):byte() + if w >= 64 then + if w == h then + return "1.8" + elseif w == h * 2 then + return "1.0" + end + end + end +end + +for _, fn in pairs(dir_list) do + local file = io.open(modpath.."/textures/"..fn, "rb") + if file then + skin_format[fn] = get_skin_format(file) + file:close() + end +end + +-- 3rd party skin-switcher support +-- may be removed from future versions as these mods do not +-- use the proper api method for setting player textures +-- +-- Auto skin format detection for 3rd party mods requires +-- that multiskin is included in 'trusted mods' + +local env = minetest.request_insecure_environment() +local skin_mod = modname +local skin_mods = {"skins", "u_skins", "simple_skins", "wardrobe"} +for _, mod in pairs(skin_mods) do + local path = minetest.get_modpath(mod) + if path then + local dir_list = minetest.get_dir_list(path.."/textures") + for _, fn in pairs(dir_list) do + if fn:find("_preview.png$") then + skin_previews[fn] = true + elseif env then + local file = env.io.open(path.."/textures/"..fn, "rb") + if file then + skin_format[fn] = get_skin_format(file) + file:close() + end + end + end + skin_mod = mod + end +end +env = nil + +local function get_player_skin(player) + local name = player:get_player_name() + if name then + local skin = nil + if skin_mod == "skins" or skin_mod == "simple_skins" then + skin = skins.skins[name] + elseif skin_mod == "u_skins" then + skin = u_skins.u_skins[name] + elseif skin_mod == "wardrobe" then + local skins = wardrobe.playerSkins or {} + if skins[name] then + return skins[name] + end + end + if skin then + return skin..".png" + end + for _, fn in pairs(dir_list) do + if fn == "player_"..name..".png" then + return fn + end + end + end + return default_skin(player) +end + +multiskin = { + model = "multiskin.b3d", + skins = player_skins, + textures = player_textures, +} + +multiskin.set_player_skin = function(player, skin) + local name = player:get_player_name() + local format = skin_format[skin] + if format then + player_format[name] = format + player:set_attribute("multiskin_format", format) + end + if not player_skins[name] then + player_skins[name] = {skin = skin} + else + player_skins[name].skin = skin + end + player:get_meta():set_string("multiskin_skin", skin) +end + +multiskin.set_player_format = function(player, format) + local name = player:get_player_name() + player_format[name] = format + player:set_attribute("multiskin_format", format) +end + +multiskin.add_preview = function(texture) + skin_previews[texture] = true +end + +multiskin.get_preview = function(player) + local skin = player:get_attribute("multiskin_skin") + if skin then + local preview = skin:gsub(".png$", "_preview.png") + if skin_previews[preview] then + return preview + end + end +end + +multiskin.update_player_visuals = function(player) + local name = player:get_player_name() + if not name or not player_skins[name] then + return + end + if player:get_meta():get_string("class") == "node" then + return + end + local anim = default.player_get_animation(player) or {} + if anim.model == "character.b3d" then + default.player_set_model(player, multiskin.model) + elseif anim.model ~= multiskin.model then + return + end + local textures = player_textures[name] or {} + local skin = player_skins[name].skin or "blank.png" + local cape = player_skins[name].cape + local layers = {} + for k, v in pairs(player_skins[name]) do + if k ~= "skin" and k ~= "cape" then + table.insert(layers, v) + end + end + local overlay = table.concat(layers, "^") + local format = player_format[name] or default_format + if format == "1.8" then + if overlay ~= "" then + skin = skin.."^"..overlay + end + textures[1] = cape or "blank.png" + textures[2] = skin + else + if cape then + skin = skin.."^"..cape + end + if overlay == "" then + overlay = "blank.png" + end + textures[1] = skin + textures[2] = overlay + end + default.player_set_textures(player, table.copy(textures)) +end + +default.player_register_model("multiskin.b3d", { + animation_speed = 30, + textures = { + "blank.png", + "blank.png", + }, + animations = { + stand = {x=0, y=79}, + lay = {x=162, y=166}, + walk = {x=168, y=187}, + mine = {x=189, y=198}, + walk_mine = {x=200, y=219}, + sit = {x=81, y=160}, + }, +}) + +minetest.register_on_joinplayer(function(player) + minetest.after(0, function(player) + local name = player:get_player_name() + local skin = player:get_meta():get("multiskin_skin") or + get_player_skin(player) + local anim = default.player_get_animation(player) or {} + player_textures[name] = anim.textures or {} + player_skins[name] = {skin=skin} + player_format[name] = player:get_attribute("multiskin_format") + multiskin.set_player_skin(player, skin) + multiskin.update_player_visuals(player) + end, player) +end) + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + if name then + player_skins[name] = nil + player_format[name] = nil + player_textures[name] = nil + end +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local name = player:get_player_name() + for field, _ in pairs(fields) do + if string.find(field, "skins_set") then + minetest.after(0, function(player) + local name = player:get_player_name() + local skin = get_player_skin(player) + multiskin.set_player_skin(player, skin) + multiskin.update_player_visuals(player) + end, player) + end + end +end) +minetest.register_chatcommand("gender", { + description = "Choose your gender", + privs = "interact", + params = "female, male", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return true, "Oh, you!" + end + if param == "" then + return true, "You are now " .. player:get_meta():get_string("gender") + elseif param == "male" then + player:get_meta():set_string("gender", "male") + if player:get_meta():get_string("multiskin_skin") == "multiskin_female.png" then + multiskin.set_player_skin(player, "multiskin_male.png") + end + multiskin.update_player_visuals(player) + return true, "You are now male." + else + player:get_meta():set_string("gender", "female") + if player:get_meta():get_string("multiskin_skin") == "multiskin_male.png" then + multiskin.set_player_skin(player, "multiskin_female.png") + end + multiskin.update_player_visuals(player) + return true, "You are now female." + end + end, +}) +minetest.register_chatcommand("multiskin", { + params = " [name] [args]", + description = "Multiskin player skin and format management", + func = function(name, param) + if not minetest.is_singleplayer() and + not minetest.check_player_privs(name, {server=true}) then + return false, "Insufficient privileges" + end + local cmd, player_name, args = string.match(param, "^([^ ]+) (.-) (.+)$") + if not args then + cmd, player_name = string.match(param, "([^ ]+) (.+)") + end + local player = nil + if player_name then + player = minetest.get_player_by_name(player_name) + else + cmd = string.match(param, "([^ ]+)") + end + if cmd == "help" then + local msg = "\nUsage: /multiskin [name] [args]\n\n".. + " format (1.0 or 1.8)\n".. + " set \n".. + " unset \n".. + " help (show this message)\n\n" + minetest.chat_send_player(name, msg) + elseif cmd == "format" and player and args then + multiskin.set_player_format(player, args) + multiskin.update_player_visuals(player) + elseif cmd == "set" and player and args then + multiskin.set_player_skin(player, args) + multiskin.update_player_visuals(player) + elseif cmd == "unset" and player then + player_skins[player_name].skin = get_player_skin(player) + player:set_attribute("multiskin_skin", nil) + multiskin.update_player_visuals(player) + else + return false, "Invalid parameters, see /multiskin help" + end + end, +}) diff --git a/mods/multiskin/mod.conf b/mods/multiskin/mod.conf new file mode 100644 index 0000000..502163d --- /dev/null +++ b/mods/multiskin/mod.conf @@ -0,0 +1 @@ +name = multiskin diff --git a/mods/multiskin/models/multiskin.b3d b/mods/multiskin/models/multiskin.b3d new file mode 100644 index 0000000..44d29ce Binary files /dev/null and b/mods/multiskin/models/multiskin.b3d differ diff --git a/mods/multiskin/models/multiskin.blend b/mods/multiskin/models/multiskin.blend new file mode 100644 index 0000000..062f175 Binary files /dev/null and b/mods/multiskin/models/multiskin.blend differ diff --git a/mods/multiskin/screenshot.png b/mods/multiskin/screenshot.png new file mode 100644 index 0000000..db234e9 Binary files /dev/null and b/mods/multiskin/screenshot.png differ diff --git a/mods/multiskin/textures/multiskin_blass.png b/mods/multiskin/textures/multiskin_blass.png new file mode 100644 index 0000000..5c582e8 Binary files /dev/null and b/mods/multiskin/textures/multiskin_blass.png differ diff --git a/mods/multiskin/textures/multiskin_blass_inv.png b/mods/multiskin/textures/multiskin_blass_inv.png new file mode 100644 index 0000000..243be31 Binary files /dev/null and b/mods/multiskin/textures/multiskin_blass_inv.png differ diff --git a/mods/multiskin/textures/multiskin_blockcolor.png b/mods/multiskin/textures/multiskin_blockcolor.png new file mode 100644 index 0000000..4c78931 Binary files /dev/null and b/mods/multiskin/textures/multiskin_blockcolor.png differ diff --git a/mods/multiskin/textures/multiskin_blockcolor_inv.png b/mods/multiskin/textures/multiskin_blockcolor_inv.png new file mode 100644 index 0000000..30d407d Binary files /dev/null and b/mods/multiskin/textures/multiskin_blockcolor_inv.png differ diff --git a/mods/multiskin/textures/multiskin_cheapie.png b/mods/multiskin/textures/multiskin_cheapie.png new file mode 100644 index 0000000..14c79d8 Binary files /dev/null and b/mods/multiskin/textures/multiskin_cheapie.png differ diff --git a/mods/multiskin/textures/multiskin_cheapie_inv.png b/mods/multiskin/textures/multiskin_cheapie_inv.png new file mode 100644 index 0000000..ec52245 Binary files /dev/null and b/mods/multiskin/textures/multiskin_cheapie_inv.png differ diff --git a/mods/multiskin/textures/multiskin_female.png b/mods/multiskin/textures/multiskin_female.png new file mode 100644 index 0000000..9c55529 Binary files /dev/null and b/mods/multiskin/textures/multiskin_female.png differ diff --git a/mods/multiskin/textures/multiskin_male.png b/mods/multiskin/textures/multiskin_male.png new file mode 100644 index 0000000..f464ab9 Binary files /dev/null and b/mods/multiskin/textures/multiskin_male.png differ diff --git a/mods/multiskin/textures/multiskin_me_only.png b/mods/multiskin/textures/multiskin_me_only.png new file mode 100644 index 0000000..ec6a213 Binary files /dev/null and b/mods/multiskin/textures/multiskin_me_only.png differ diff --git a/mods/multiskin/textures/multiskin_me_only_inv.png b/mods/multiskin/textures/multiskin_me_only_inv.png new file mode 100644 index 0000000..82e892a Binary files /dev/null and b/mods/multiskin/textures/multiskin_me_only_inv.png differ diff --git a/mods/multiskin/textures/multiskin_sam_ii_winter.png b/mods/multiskin/textures/multiskin_sam_ii_winter.png new file mode 100644 index 0000000..a156434 Binary files /dev/null and b/mods/multiskin/textures/multiskin_sam_ii_winter.png differ diff --git a/mods/multiskin/textures/multiskin_sam_ii_winter_inv.png b/mods/multiskin/textures/multiskin_sam_ii_winter_inv.png new file mode 100644 index 0000000..c55c79a Binary files /dev/null and b/mods/multiskin/textures/multiskin_sam_ii_winter_inv.png differ diff --git a/mods/multiskin/textures/multiskin_temerlime.png b/mods/multiskin/textures/multiskin_temerlime.png new file mode 100644 index 0000000..47b40cb Binary files /dev/null and b/mods/multiskin/textures/multiskin_temerlime.png differ diff --git a/mods/multiskin/textures/multiskin_temerlime_inv.png b/mods/multiskin/textures/multiskin_temerlime_inv.png new file mode 100644 index 0000000..37485ea Binary files /dev/null and b/mods/multiskin/textures/multiskin_temerlime_inv.png differ diff --git a/mods/multiskin/textures/multiskin_urotsuki.png b/mods/multiskin/textures/multiskin_urotsuki.png new file mode 100644 index 0000000..376b95a Binary files /dev/null and b/mods/multiskin/textures/multiskin_urotsuki.png differ diff --git a/mods/multiskin/textures/multiskin_urotsuki_inv.png b/mods/multiskin/textures/multiskin_urotsuki_inv.png new file mode 100644 index 0000000..3c78409 Binary files /dev/null and b/mods/multiskin/textures/multiskin_urotsuki_inv.png differ diff --git a/mods/multiskin/textures/skins_here.txt b/mods/multiskin/textures/skins_here.txt new file mode 100644 index 0000000..0a667b8 --- /dev/null +++ b/mods/multiskin/textures/skins_here.txt @@ -0,0 +1 @@ +Place your player skins here named as `player_.png` diff --git a/mods/player_api/README.txt b/mods/player_api/README.txt new file mode 100644 index 0000000..22d040c --- /dev/null +++ b/mods/player_api/README.txt @@ -0,0 +1,32 @@ +Minetest Game mod: player_api +============================= +See license.txt for license information. + +Provides an API to allow multiple mods to set player models and textures. +Also sets the default model, texture, and player flags. + +Authors of source code +---------------------- +Originally by celeron55, Perttu Ahola (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures, models and sounds) +---------------------------------------------- +stujones11 (CC BY-SA 3.0): + character.b3d + character.blend -- Both derived from a model by MirceaKitsune (CC BY-SA 3.0) + +Jordach (CC BY-SA 3.0): + character.png + +paramat (CC BY-SA 3.0): + gui_hotbar.png + gui_hotbar_selected.png + +celeron55, Perttu Ahola (CC BY-SA 3.0): + player.png + player_back.png + +sonictechtonic (CC BY 3.0): +https://www.freesound.org/people/sonictechtonic/sounds/241872/ + player_damage.ogg diff --git a/mods/player_api/api.lua b/mods/player_api/api.lua new file mode 100644 index 0000000..e309b08 --- /dev/null +++ b/mods/player_api/api.lua @@ -0,0 +1,139 @@ +-- Minetest 0.4 mod: player +-- See README.txt for licensing and other information. + +player_api = {} + +-- Player animation blending +-- Note: This is currently broken due to a bug in Irrlicht, leave at 0 +local animation_blend = 0 + +player_api.registered_models = { } + +-- Local for speed. +local models = player_api.registered_models + +function player_api.register_model(name, def) + models[name] = def +end + +-- Player stats and animations +local player_model = {} +local player_textures = {} +local player_anim = {} +local player_sneak = {} +player_api.player_attached = {} + +function player_api.get_animation(player) + local name = player:get_player_name() + return { + model = player_model[name], + textures = player_textures[name], + animation = player_anim[name], + } +end + +-- Called when a player's appearance needs to be updated +function player_api.set_model(player, model_name) + local name = player:get_player_name() + local model = models[model_name] + if model then + if player_model[name] == model_name then + return + end + player:set_properties({ + mesh = model_name, + textures = player_textures[name] or model.textures, + visual = "mesh", + visual_size = model.visual_size or {x = 1, y = 1}, + collisionbox = model.collisionbox or {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + stepheight = model.stepheight or 0.6, + eye_height = model.eye_height or 1.47, + }) + player_api.set_animation(player, "stand") + else + player:set_properties({ + textures = {"player.png", "player_back.png"}, + visual = "upright_sprite", + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.75, 0.3}, + stepheight = 0.6, + eye_height = 1.625, + }) + end + player_model[name] = model_name +end + +function player_api.set_textures(player, textures) + local name = player:get_player_name() + local model = models[player_model[name]] + local model_textures = model and model.textures or nil + player_textures[name] = textures or model_textures + player:set_properties({textures = textures or model_textures,}) +end + +function player_api.set_animation(player, anim_name, speed) + local name = player:get_player_name() + if player_anim[name] == anim_name then + return + end + local model = player_model[name] and models[player_model[name]] + if not (model and model.animations[anim_name]) then + return + end + local anim = model.animations[anim_name] + player_anim[name] = anim_name + player:set_animation(anim, speed or model.animation_speed, animation_blend) +end + +minetest.register_on_leaveplayer(function(player) + local name = player:get_player_name() + player_model[name] = nil + player_anim[name] = nil + player_textures[name] = nil +end) + +-- Localize for better performance. +local player_set_animation = player_api.set_animation +local player_attached = player_api.player_attached + +-- Check each player and apply animations +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local name = player:get_player_name() + local model_name = player_model[name] + local model = model_name and models[model_name] + if model and not player_attached[name] then + local controls = player:get_player_control() + local walking = false + local animation_speed_mod = model.animation_speed or 30 + + -- Determine if the player is walking + if controls.up or controls.down or controls.left or controls.right then + walking = true + end + + -- Determine if the player is sneaking, and reduce animation speed if so + if controls.sneak then + animation_speed_mod = animation_speed_mod / 2 + end + + -- Apply animations based on what the player is doing + if player:get_hp() == 0 then + player_set_animation(player, "lay") + elseif walking then + if player_sneak[name] ~= controls.sneak then + player_anim[name] = nil + player_sneak[name] = controls.sneak + end + if controls.LMB then + player_set_animation(player, "walk_mine", animation_speed_mod) + else + player_set_animation(player, "walk", animation_speed_mod) + end + elseif controls.LMB then + player_set_animation(player, "mine") + else + player_set_animation(player, "stand", animation_speed_mod) + end + end + end +end) diff --git a/mods/player_api/init.lua b/mods/player_api/init.lua new file mode 100644 index 0000000..7a1f353 --- /dev/null +++ b/mods/player_api/init.lua @@ -0,0 +1,34 @@ +dofile(minetest.get_modpath("player_api") .. "/api.lua") + +-- Default player appearance +player_api.register_model("character.b3d", { + animation_speed = 30, + textures = {"character.png", }, + animations = { + -- Standard animations. + stand = {x = 0, y = 79}, + lay = {x = 162, y = 166}, + walk = {x = 168, y = 187}, + mine = {x = 189, y = 198}, + walk_mine = {x = 200, y = 219}, + sit = {x = 81, y = 160}, + }, + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + stepheight = 0.6, + eye_height = 1.47, +}) + +-- Update appearance when the player joins +minetest.register_on_joinplayer(function(player) + player_api.player_attached[player:get_player_name()] = false + player_api.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 + ) + player:hud_set_hotbar_image("gui_hotbar.png") + player:hud_set_hotbar_selected_image("gui_hotbar_selected.png") +end) diff --git a/mods/player_api/license.txt b/mods/player_api/license.txt new file mode 100644 index 0000000..69bb2f8 --- /dev/null +++ b/mods/player_api/license.txt @@ -0,0 +1,84 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2011-2018 celeron55, Perttu Ahola +Copyright (C) 2011-2018 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, models and sounds) +----------------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2011-2018 celeron55, Perttu Ahola +Copyright (C) 2012-2018 Jordach +Copyright (C) 2018 stujones11 +Copyright (C) 2018 paramat + +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/ + +------------------------------------ + +Attribution 3.0 Unported (CC BY 3.0) +Copyright (C) 2014-2018 sonictechtonic + +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. + +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/3.0/ + diff --git a/mods/player_api/models/character.b3d b/mods/player_api/models/character.b3d new file mode 100644 index 0000000..b3b772a Binary files /dev/null and b/mods/player_api/models/character.b3d differ diff --git a/mods/player_api/models/character.blend b/mods/player_api/models/character.blend new file mode 100644 index 0000000..652579c Binary files /dev/null and b/mods/player_api/models/character.blend differ diff --git a/mods/player_api/models/character.png b/mods/player_api/models/character.png new file mode 100644 index 0000000..0502178 Binary files /dev/null and b/mods/player_api/models/character.png differ diff --git a/mods/player_api/sounds/player_damage.ogg b/mods/player_api/sounds/player_damage.ogg new file mode 100644 index 0000000..7888087 Binary files /dev/null and b/mods/player_api/sounds/player_damage.ogg differ diff --git a/mods/player_api/textures/gui_hotbar.png b/mods/player_api/textures/gui_hotbar.png new file mode 100644 index 0000000..7bc7887 Binary files /dev/null and b/mods/player_api/textures/gui_hotbar.png differ diff --git a/mods/player_api/textures/gui_hotbar_selected.png b/mods/player_api/textures/gui_hotbar_selected.png new file mode 100644 index 0000000..7203e9a Binary files /dev/null and b/mods/player_api/textures/gui_hotbar_selected.png differ diff --git a/mods/player_api/textures/player.png b/mods/player_api/textures/player.png new file mode 100644 index 0000000..6d61c43 Binary files /dev/null and b/mods/player_api/textures/player.png differ diff --git a/mods/player_api/textures/player_back.png b/mods/player_api/textures/player_back.png new file mode 100644 index 0000000..5e9ef05 Binary files /dev/null and b/mods/player_api/textures/player_back.png differ diff --git a/mods/protector/README.md b/mods/protector/README.md new file mode 100644 index 0000000..3c0016f --- /dev/null +++ b/mods/protector/README.md @@ -0,0 +1,121 @@ +Protector Redo mod [protect] + +Protector redo for minetest is a mod that protects a players builds by placing +a block that stops other players from digging or placing blocks in that area. + +based on glomie's mod, remade by Zeg9 and rewritten by TenPlus1. + +https://forum.minetest.net/viewtopic.php?f=11&t=9376 + +Change log: + +- 0.1 - Initial release +- 0.2 - Texture update +- 0.3 - Added Protection Logo to blend in with player builds +- 0.4 - Code tweak for 0.4.10+ +- 0.5 - Added protector.radius variable in init.lua (default: 5) +- 0.6 - Added Protected Doors (wood and steel) and Protected Chest +- 0.7 - Protected Chests now have "To Chest" and "To Inventory" buttons to copy + contents across, also chests can be named +- 0.8 - Updated to work with Minetest 0.4.12, simplified textures +- 0.9 - Tweaked code +- 1.0 - Only owner can remove protector +- 1.1 - Set 'protector_pvp = true' in minetest.conf to disable pvp in protected + areas except your own, also setting protector_pvp_spawn higher than 0 will + disable pvp around spawn area with the radius you entered +- 1.2 - Shift and click support added with Minetest 0.4.13 to quickly copy stacks + to and from protected chest +- 1.3 - Moved protector on_place into node itself, protector zone display changed + from 10 to 5 seconds, general code tidy +- 1.4 - Changed protector recipes to give single item instead of 4, added + button + to interface, tweaked and tidied code, added admin command /delprot to remove + protectors in bulk from banned/old players +- 1.5 - Added much requested protected trapdoor +- 1.6 - Added protector_drop (true or false) and protector_hurt (hurt by this num) + variables to minetest.conf settings to stop players breaking protected + areas by dropping tools and hurting player. +- 1.7 - Included an edited version of WTFPL doors mod since protected doors didn't + work with the doors mod in the latest daily build... Now it's fine :) + added support for "protection_bypass" privelage. +- 1.8 - Added 'protector_flip' setting to stop players using lag to grief into + another players house, it flips them around to stop them digging. +- 1.9 - Renamed 'protector_pvp_spawn' setting to 'protector_spawn' which protects + an area around static spawnpoint and disables pvp if active. + (note: previous name can still be used) +- 2.0 - Added protector placement tool (thanks to Shara) so that players can easily + stand on a protector, face in a direction and it places a new one at a set + distance to cover protection radius. Added /protector_show command (thanks agaran) + Protectors and chest cannot be moved by mesecon pistons or machines. +- 2.1 - Added 'protector_night_pvp' setting so night-time becomes a free for all and + players can hurt one another even inside protected areas (not spawn protected) +- 2.2 - Updated protector tool so that player only needs to stand nearby (2 block radius) + It can also place vertically (up and down) as well. New protector recipe added. +- 2.3 - Localise many of the protector functions and tidy code. +- 2.4 - Update to newer functions, Minetest 0.4.16 needed to run now. +- 2.5 - Added HUD text to show when player is inside a protected area (updates every 5 seconds) +- 2.6 - Add protection against CSM tampering, updated Intllib support (thanks codexp), tweaked block textures + +Lucky Blocks: 10 + + +Usage: (requires server privelage) + +list names to remove + + /protector_remove + +remove specific user names + + /protector_remove name1 name2 + +remove all names from list + + /protector_remove - + +Whenever a player is near any protectors with name1 or name2 then it will be +replaced by an air block. + + +show owner name to replace + + /protector_replace + +replace owner with new name + + /protector_replace owner new_owner + +reset name list + + /protector_replace - + + +show protected areas of your nearby protectors (max of 5) + /protector_show + + +The following lines can be added to your minetest.conf file to configure specific features of the mod: + +protector_radius = 5 +- Sets the area around each protection node so that other players cannot dig, place or enter through protected doors or chests. + +protector_pvp = true +- true or false this setting disabled pvp inside of protected areas for all players apart from those listed on the protector node. + +protector_night_pvp = false +- when true this setting enables pvp at night time only, even inside protected areas, requires protector_pvp to be active to work. + +protector_spawn = 10 +- Sets an area 10 nodes around static spawnpoint that is protected. + +protector_hurt = 2 +- When set to above 0, players digging in protected areas will be hurt by 2 health points (or whichever number it's set to) + +protector_flip = true +- When true players who dig inside a protected area will flipped around to stop them using lag to grief into someone else's build + + +Protector Tool + +Can be crafted with a protector surrounded by steel ingots and is used to place new protectors at a set distance of protector.radius in all directions including up and down simply by looking in a direction. + +Use by standing near an existing protector, looking in a direction and using as a tool, hold sneak/shift to place new protector containing member list from inside nearest one. diff --git a/mods/protector/admin.lua b/mods/protector/admin.lua new file mode 100644 index 0000000..dad48a8 --- /dev/null +++ b/mods/protector/admin.lua @@ -0,0 +1,146 @@ + +local S = protector.intllib +local removal_names = "" +local replace_names = "" + +minetest.register_chatcommand("protector_remove", { + params = S(""), + description = S("Remove Protectors around players (separate names with spaces)"), + privs = {server = true}, + func = function(name, param) + + if not param or param == "" then + + minetest.chat_send_player(name, + S("Protector Names to remove: @1", + removal_names)) + + return + end + + if param == "-" then + + minetest.chat_send_player(name, + S("Name List Reset")) + + removal_names = "" + + return + end + + removal_names = param + + end, +}) + + +minetest.register_chatcommand("protector_replace", { + params = S(" "), + description = S("Replace Protector Owner with name provided"), + privs = {server = true}, + func = function(name, param) + + -- reset list to empty + if param == "-" then + + minetest.chat_send_player(name, S("Name List Reset")) + + replace_names = "" + + return + end + + -- show name info + if param == "" + and replace_names ~= "" then + + local names = replace_names:split(" ") + + minetest.chat_send_player(name, + S("Replacing Protector name '@1' with '@2'", + names[1] or "", names[2] or "")) + + return + end + + replace_names = param + + end, +}) + + +minetest.register_abm({ + nodenames = {"protector:protect", "protector:protect2"}, + interval = 8, + chance = 1, + catch_up = false, + action = function(pos, node) + + if removal_names == "" + and replace_names == "" then + return + end + + local meta = minetest.get_meta(pos) + + if not meta then return end + + local owner = meta:get_string("owner") + + if removal_names ~= "" then + + local names = removal_names:split(" ") + + for _, n in pairs(names) do + if n == owner then + minetest.set_node(pos, {name = "air"}) + end + end + end + + if replace_names ~= "" then + + local names = replace_names:split(" ") + + if names[1] and names[2] and owner == names[1] then + meta:set_string("owner", names[2]) + meta:set_string("infotext", S("Protection (owned by @1)", names[2])) + end + + end + end +}) + +-- get protection radius +local r = tonumber(minetest.settings:get("protector_radius")) or 5 + +-- show protection areas of nearby protectors owned by you (thanks agaran) +minetest.register_chatcommand("protector_show", { + params = "", + description = S("Show protected areas of your nearby protectors"), + privs = {}, + func = function(name, param) + + local player = minetest.get_player_by_name(name) + local pos = player:get_pos() + + -- find the protector nodes + local pos = minetest.find_nodes_in_area( + {x = pos.x - r, y = pos.y - r, z = pos.z - r}, + {x = pos.x + r, y = pos.y + r, z = pos.z + r}, + {"protector:protect", "protector:protect2"}) + + local meta, owner + + -- show a maximum of 5 protected areas only + for n = 1, math.min(#pos, 5) do + + meta = minetest.get_meta(pos[n]) + owner = meta:get_string("owner") or "" + + if owner == name then + minetest.add_entity(pos[n], "protector:display") + end + end + end +}) diff --git a/mods/protector/depends.txt b/mods/protector/depends.txt new file mode 100644 index 0000000..4713add --- /dev/null +++ b/mods/protector/depends.txt @@ -0,0 +1,4 @@ +default +intllib? +lucky_block? +mesecons_mvps? diff --git a/mods/protector/description.txt b/mods/protector/description.txt new file mode 100644 index 0000000..587fee8 --- /dev/null +++ b/mods/protector/description.txt @@ -0,0 +1 @@ +Lets players craft special blocks to protect their builds or disable PVP in areas. \ No newline at end of file diff --git a/mods/protector/doors_chest.lua b/mods/protector/doors_chest.lua new file mode 100644 index 0000000..6d4408b --- /dev/null +++ b/mods/protector/doors_chest.lua @@ -0,0 +1,689 @@ + +-- Since the doors mod has changed in the latest daily builds I have taken the +-- WTFPL licenced code from the old doors mod and included an edited version +-- within this mod for local use. + +local S = protector.intllib +local F = minetest.formspec_escape + +-- Registers a door +function register_door(name, def) + def.groups.not_in_creative_inventory = 1 + + local box = {{-0.5, -0.5, -0.5, 0.5, 0.5, -0.5+1.5/16}} + + def.node_box_bottom = box + def.node_box_top = box + def.selection_box_bottom = box + def.selection_box_top = box + def.sound_close_door = "doors_door_close" + def.sound_open_door = "doors_door_open" + + minetest.register_craftitem(name, { + description = def.description, + inventory_image = def.inventory_image, + + on_place = function(itemstack, placer, pointed_thing) + if not pointed_thing.type == "node" then + return itemstack + end + + local ptu = pointed_thing.under + local nu = minetest.get_node(ptu) + if minetest.registered_nodes[nu.name] + and minetest.registered_nodes[nu.name].on_rightclick then + return minetest.registered_nodes[nu.name].on_rightclick(ptu, nu, placer, itemstack) + end + + local pt = pointed_thing.above + local pt2 = {x=pt.x, y=pt.y, z=pt.z} + pt2.y = pt2.y+1 + if + not minetest.registered_nodes[minetest.get_node(pt).name].buildable_to or + not minetest.registered_nodes[minetest.get_node(pt2).name].buildable_to or + not placer or + not placer:is_player() + then + return itemstack + end + + if minetest.is_protected(pt, placer:get_player_name()) or + minetest.is_protected(pt2, placer:get_player_name()) then + minetest.record_protection_violation(pt, placer:get_player_name()) + return itemstack + end + + local p2 = minetest.dir_to_facedir(placer:get_look_dir()) + local pt3 = {x=pt.x, y=pt.y, z=pt.z} + if p2 == 0 then + pt3.x = pt3.x-1 + elseif p2 == 1 then + pt3.z = pt3.z+1 + elseif p2 == 2 then + pt3.x = pt3.x+1 + elseif p2 == 3 then + pt3.z = pt3.z-1 + end + if minetest.get_item_group(minetest.get_node(pt3).name, "door") == 0 then + minetest.set_node(pt, {name=name.."_b_1", param2=p2}) + minetest.set_node(pt2, {name=name.."_t_1", param2=p2}) + else + minetest.set_node(pt, {name=name.."_b_2", param2=p2}) + minetest.set_node(pt2, {name=name.."_t_2", param2=p2}) + minetest.get_meta(pt):set_int("right", 1) + minetest.get_meta(pt2):set_int("right", 1) + end + + if not minetest.setting_getbool("creative_mode") then + itemstack:take_item() + end + return itemstack + end, + }) + + local tt = def.tiles_top + local tb = def.tiles_bottom + + local function after_dig_node(pos, name, digger) + local node = minetest.get_node(pos) + if node.name == name then + minetest.node_dig(pos, node, digger) + end + end + + local function on_rightclick(pos, dir, check_name, replace, replace_dir, params) + pos.y = pos.y+dir + if minetest.get_node(pos).name ~= check_name then + return + end + local p2 = minetest.get_node(pos).param2 + p2 = params[p2+1] + + minetest.swap_node(pos, {name=replace_dir, param2=p2}) + + pos.y = pos.y-dir + minetest.swap_node(pos, {name=replace, param2=p2}) + + local snd_1 = def.sound_close_door + local snd_2 = def.sound_open_door + if params[1] == 3 then + snd_1 = def.sound_open_door + snd_2 = def.sound_close_door + end + + if minetest.get_meta(pos):get_int("right") ~= 0 then + minetest.sound_play(snd_1, {pos = pos, gain = 0.3, max_hear_distance = 10}) + else + minetest.sound_play(snd_2, {pos = pos, gain = 0.3, max_hear_distance = 10}) + end + end + + local function on_rotate(pos, node, dir, user, check_name, mode, new_param2) + + if mode ~= screwdriver.ROTATE_FACE then + return false + end + + pos.y = pos.y + dir + if not minetest.get_node(pos).name == check_name then + return false + end + if minetest.is_protected(pos, user:get_player_name()) then + minetest.record_protection_violation(pos, user:get_player_name()) + return false + end + + local node2 = minetest.get_node(pos) + node2.param2 = (node2.param2 + 1) % 4 + minetest.swap_node(pos, node2) + + pos.y = pos.y - dir + node.param2 = (node.param2 + 1) % 4 + minetest.swap_node(pos, node) + return true + end + + minetest.register_node(name.."_b_1", { + tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = name, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = def.node_box_bottom + }, + selection_box = { + type = "fixed", + fixed = def.selection_box_bottom + }, + groups = def.groups, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + pos.y = pos.y+1 + after_dig_node(pos, name.."_t_1", digger) + end, + + on_rightclick = function(pos, node, clicker) + if not minetest.is_protected(pos, clicker:get_player_name()) then + on_rightclick(pos, 1, name.."_t_1", name.."_b_2", name.."_t_2", {1,2,3,0}) + end + end, + + on_rotate = function(pos, node, user, mode, new_param2) + return on_rotate(pos, node, 1, user, name.."_t_1", mode) + end, + + sounds = def.sounds, + sunlight_propagates = def.sunlight, + on_blast = function() end, + }) + + minetest.register_node(name.."_t_1", { + tiles = {tt[2], tt[2], tt[2], tt[2], tt[1], tt[1].."^[transformfx"}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = def.node_box_top + }, + selection_box = { + type = "fixed", + fixed = def.selection_box_top + }, + groups = def.groups, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + pos.y = pos.y-1 + after_dig_node(pos, name.."_b_1", digger) + end, + + on_rightclick = function(pos, node, clicker) + if not minetest.is_protected(pos, clicker:get_player_name()) then + on_rightclick(pos, -1, name.."_b_1", name.."_t_2", name.."_b_2", {1,2,3,0}) + end + end, + + on_rotate = function(pos, node, user, mode, new_param2) + return on_rotate(pos, node, -1, user, name.."_b_1", mode) + end, + + sounds = def.sounds, + sunlight_propagates = def.sunlight, + on_blast = function() end, + }) + + minetest.register_node(name.."_b_2", { + tiles = {tb[2], tb[2], tb[2], tb[2], tb[1].."^[transformfx", tb[1]}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = name, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = def.node_box_bottom + }, + selection_box = { + type = "fixed", + fixed = def.selection_box_bottom + }, + groups = def.groups, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + pos.y = pos.y+1 + after_dig_node(pos, name.."_t_2", digger) + end, + + on_rightclick = function(pos, node, clicker) + if not minetest.is_protected(pos, clicker:get_player_name()) then + on_rightclick(pos, 1, name.."_t_2", name.."_b_1", name.."_t_1", {3,0,1,2}) + end + end, + + on_rotate = function(pos, node, user, mode, new_param2) + return on_rotate(pos, node, 1, user, name.."_t_2", mode) + end, + + sounds = def.sounds, + sunlight_propagates = def.sunlight, + on_blast = function() end, + }) + + minetest.register_node(name.."_t_2", { + tiles = {tt[2], tt[2], tt[2], tt[2], tt[1].."^[transformfx", tt[1]}, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + drop = "", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = def.node_box_top + }, + selection_box = { + type = "fixed", + fixed = def.selection_box_top + }, + groups = def.groups, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + pos.y = pos.y-1 + after_dig_node(pos, name.."_b_2", digger) + end, + + on_rightclick = function(pos, node, clicker) + if not minetest.is_protected(pos, clicker:get_player_name()) then + on_rightclick(pos, -1, name.."_b_2", name.."_t_1", name.."_b_1", {3,0,1,2}) + end + end, + + on_rotate = function(pos, node, user, mode, new_param2) + return on_rotate(pos, node, -1, user, name.."_b_2", mode) + end, + + sounds = def.sounds, + sunlight_propagates = def.sunlight, + on_blast = function() end, + }) + +end + +-- Protected Wooden Door + +local name = "protector:door_wood" + +register_door(name, { + description = S("Protected Wooden Door"), + inventory_image = "doors_wood.png^protector_logo.png", + groups = { + snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, + unbreakable = 1, --door = 1 + }, + tiles_bottom = {"doors_wood_b.png^protector_logo.png", "doors_brown.png"}, + tiles_top = {"doors_wood_a.png", "doors_brown.png"}, + sounds = default.node_sound_wood_defaults(), + sunlight = false, +}) + +minetest.register_craft({ + output = name, + recipe = { + {"group:wood", "group:wood"}, + {"group:wood", "default:copper_ingot"}, + {"group:wood", "group:wood"} + } +}) + +minetest.register_craft({ + output = name, + recipe = { + {"doors:door_wood", "default:copper_ingot"} + } +}) + +-- Protected Steel Door + +local name = "protector:door_steel" + +register_door(name, { + description = S("Protected Steel Door"), + inventory_image = "doors_steel.png^protector_logo.png", + groups = { + snappy = 1, bendy = 2, cracky = 1, + level = 2, unbreakable = 1, -- door = 1 + }, + tiles_bottom = {"doors_steel_b.png^protector_logo.png", "doors_grey.png"}, + tiles_top = {"doors_steel_a.png", "doors_grey.png"}, + sounds = default.node_sound_wood_defaults(), + sunlight = false, +}) + +minetest.register_craft({ + output = name, + recipe = { + {"default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:copper_ingot"}, + {"default:steel_ingot", "default:steel_ingot"} + } +}) + +minetest.register_craft({ + output = name, + recipe = { + {"doors:door_steel", "default:copper_ingot"} + } +}) + +----trapdoor---- + +function register_trapdoor(name, def) + local name_closed = name + local name_opened = name.."_open" + + def.on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + if minetest.is_protected(pos, clicker:get_player_name()) then + return + end + local newname = node.name == name_closed and name_opened or name_closed + local sound = false + if node.name == name_closed then sound = "doors_door_open" end + if node.name == name_opened then sound = "doors_door_close" end + if sound then + minetest.sound_play(sound, {pos = pos, gain = 0.3, max_hear_distance = 10}) + end + minetest.swap_node(pos, {name = newname, param1 = node.param1, param2 = node.param2}) + end + + -- Common trapdoor configuration + def.drawtype = "nodebox" + def.paramtype = "light" + def.paramtype2 = "facedir" + def.is_ground_content = false + + local def_opened = table.copy(def) + local def_closed = table.copy(def) + + def_closed.node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} + } + def_closed.selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} + } + def_closed.tiles = { def.tile_front, def.tile_front, def.tile_side, def.tile_side, + def.tile_side, def.tile_side } + + def_opened.node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} + } + def_opened.selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} + } + def_opened.tiles = { def.tile_side, def.tile_side, + def.tile_side .. '^[transform3', + def.tile_side .. '^[transform1', + def.tile_front, def.tile_front } + + def_opened.drop = name_closed + def_opened.groups.not_in_creative_inventory = 1 + + minetest.register_node(name_opened, def_opened) + minetest.register_node(name_closed, def_closed) +end + +-- Protected Wooden Trapdoor + +register_trapdoor("protector:trapdoor", { + description = S("Protected Trapdoor"), + inventory_image = "doors_trapdoor.png^protector_logo.png", + wield_image = "doors_trapdoor.png^protector_logo.png", + tile_front = "doors_trapdoor.png^protector_logo.png", + tile_side = "doors_trapdoor_side.png", + groups = { + snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, + unbreakable = 1, --door = 1 + }, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_craft({ + output = 'protector:trapdoor 2', + recipe = { + {'group:wood', 'default:copper_ingot', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + {'', '', ''}, + } +}) + +minetest.register_craft({ + output = "protector:trapdoor", + recipe = { + {"doors:trapdoor", "default:copper_ingot"} + } +}) + +-- Protected Steel Trapdoor + +register_trapdoor("protector:trapdoor_steel", { + description = S("Protected Steel Trapdoor"), + inventory_image = "doors_trapdoor_steel.png^protector_logo.png", + wield_image = "doors_trapdoor_steel.png^protector_logo.png", + tile_front = "doors_trapdoor_steel.png^protector_logo.png", + tile_side = "doors_trapdoor_steel_side.png", + groups = { + snappy = 1, bendy = 2, cracky = 1, melty = 2, level = 2, + unbreakable = 1, --door = 1 + }, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_craft({ + output = 'protector:trapdoor_steel', + recipe = { + {'default:copper_ingot', 'default:steel_ingot'}, + {'default:steel_ingot', 'default:steel_ingot'}, + } +}) + +minetest.register_craft({ + output = "protector:trapdoor_steel", + recipe = { + {"doors:trapdoor_steel", "default:copper_ingot"} + } +}) + +-- Protected Chest + +minetest.register_node("protector:chest", { + description = S("Protected 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^protector_logo.png" + }, + paramtype2 = "facedir", + groups = {choppy = 2, oddly_breakable_by_hand = 2, unbreakable = 1}, + legacy_facedir_simple = true, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), + + on_construct = function(pos) + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + meta:set_string("infotext", S("Protected Chest")) + meta:set_string("name", "") + inv:set_size("main", 8 * 4) + end, + + can_dig = function(pos,player) + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + if inv:is_empty("main") then + + if not minetest.is_protected(pos, player:get_player_name()) then + return true + end + end + end, + + on_metadata_inventory_put = function(pos, listname, index, stack, player) + + minetest.log("action", S("@1 moves stuff to protected chest at @2", + player:get_player_name(), minetest.pos_to_string(pos))) + end, + + on_metadata_inventory_take = function(pos, listname, index, stack, player) + + minetest.log("action", S("@1 takes stuff from protected chest at @2", + player:get_player_name(), minetest.pos_to_string(pos))) + end, + + on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + + minetest.log("action", S("@1 moves stuff inside protected chest at @2", + player:get_player_name(), minetest.pos_to_string(pos))) + end, + + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + return stack:get_count() + end, + + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + return stack:get_count() + end, + + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + return count + end, + + on_rightclick = function(pos, node, clicker) + + if minetest.is_protected(pos, clicker:get_player_name()) then + return + end + + local meta = minetest.get_meta(pos) + + if not meta then + return + end + + local spos = pos.x .. "," .. pos.y .. "," ..pos.z + local formspec = "size[8,9]" + .. default.gui_bg + .. default.gui_bg_img + .. default.gui_slots + .. "list[nodemeta:".. spos .. ";main;0,0.3;8,4;]" + .. "button[0,4.5;2,0.25;toup;" .. F(S("To Chest")) .. "]" + .. "field[2.3,4.8;4,0.25;chestname;;" + .. meta:get_string("name") .. "]" + .. "button[6,4.5;2,0.25;todn;" .. F(S("To Inventory")) .. "]" + .. "list[current_player;main;0,5;8,1;]" + .. "list[current_player;main;0,6.08;8,3;8]" + .. "listring[nodemeta:" .. spos .. ";main]" + .. "listring[current_player;main]" + + minetest.show_formspec( + clicker:get_player_name(), + "protector:chest_" .. minetest.pos_to_string(pos), + formspec) + end, + + on_blast = function() end, +}) + +-- Protected Chest formspec buttons + +minetest.register_on_player_receive_fields(function(player, formname, fields) + + if string.sub(formname, 0, string.len("protector:chest_")) ~= "protector:chest_" then + return + end + + local pos_s = string.sub(formname,string.len("protector:chest_") + 1) + local pos = minetest.string_to_pos(pos_s) + + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + local meta = minetest.get_meta(pos) ; if not meta then return end + local chest_inv = meta:get_inventory() ; if not chest_inv then return end + local player_inv = player:get_inventory() + local leftover + + if fields.toup then + + -- copy contents of players inventory to chest + for i, v in ipairs(player_inv:get_list("main") or {}) do + + if chest_inv:room_for_item("main", v) then + + leftover = chest_inv:add_item("main", v) + + player_inv:remove_item("main", v) + + if leftover + and not leftover:is_empty() then + player_inv:add_item("main", v) + end + end + end + + elseif fields.todn then + + -- copy contents of chest to players inventory + for i, v in ipairs(chest_inv:get_list("main") or {}) do + + if player_inv:room_for_item("main", v) then + + leftover = player_inv:add_item("main", v) + + chest_inv:remove_item("main", v) + + if leftover + and not leftover:is_empty() then + chest_inv:add_item("main", v) + end + end + end + + elseif fields.chestname then + + -- change chest infotext to display name + if fields.chestname ~= "" then + + meta:set_string("name", fields.chestname) + meta:set_string("infotext", + S("Protected Chest (@1)", fields.chestname)) + else + meta:set_string("infotext", S("Protected Chest")) + end + + end +end) + +-- Protected Chest recipes + +minetest.register_craft({ + output = 'protector:chest', + recipe = { + {'group:wood', 'group:wood', 'group:wood'}, + {'group:wood', 'default:copper_ingot', 'group:wood'}, + {'group:wood', 'group:wood', 'group:wood'}, + } +}) + +minetest.register_craft({ + output = 'protector:chest', + recipe = { + {'default:chest', 'default:copper_ingot', ''}, + } +}) diff --git a/mods/protector/hud.lua b/mods/protector/hud.lua new file mode 100644 index 0000000..c74a4dc --- /dev/null +++ b/mods/protector/hud.lua @@ -0,0 +1,61 @@ + +local S = protector.intllib +local radius = (tonumber(minetest.setting_get("protector_radius")) or 5) +local hud = {} +local hud_timer = 0 + +minetest.register_globalstep(function(dtime) + + -- every 5 seconds + hud_timer = hud_timer + dtime + if hud_timer < 5 then + return + end + hud_timer = 0 + + for _, player in pairs(minetest.get_connected_players()) do + + local name = player:get_player_name() + local pos = vector.round(player:get_pos()) + local hud_text = "" + + local protectors = minetest.find_nodes_in_area( + {x = pos.x - radius , y = pos.y - radius , z = pos.z - radius}, + {x = pos.x + radius , y = pos.y + radius , z = pos.z + radius}, + {"protector:protect","protector:protect2"}) + + if #protectors > 0 then + local npos = protectors[1] + local meta = minetest.get_meta(npos) + local nodeowner = meta:get_string("owner") + + hud_text = S("Owner: @1", nodeowner) + end + + if not hud[name] then + + hud[name] = {} + + hud[name].id = player:hud_add({ + hud_elem_type = "text", + name = "Protector Area", + number = 0xFFFF22, + position = {x=0, y=0.95}, + offset = {x=8, y=-8}, + text = hud_text, + scale = {x=200, y=60}, + alignment = {x=1, y=-1}, + }) + + return + + else + + player:hud_change(hud[name].id, "text", hud_text) + end + end +end) + +minetest.register_on_leaveplayer(function(player) + hud[player:get_player_name()] = nil +end) diff --git a/mods/protector/init.lua b/mods/protector/init.lua new file mode 100644 index 0000000..c5db67a --- /dev/null +++ b/mods/protector/init.lua @@ -0,0 +1,667 @@ + +-- Load support for intllib. +local MP = minetest.get_modpath(minetest.get_current_modname()) +local S = dofile(MP .. "/intllib.lua") +local F = minetest.formspec_escape + + +protector = {} +protector.mod = "redo" +protector.modpath = MP +protector.intllib = S + +local protector_max_share_count = 12 +-- get minetest.conf settings +local protector_radius = tonumber(minetest.settings:get("protector_radius")) or 5 +local protector_flip = minetest.settings:get_bool("protector_flip") or false +local protector_hurt = tonumber(minetest.settings:get("protector_hurt")) or 0 +local protector_spawn = tonumber(minetest.settings:get("protector_spawn") + or minetest.settings:get("protector_pvp_spawn")) or 0 + +-- get static spawn position +local statspawn = minetest.string_to_pos(minetest.settings:get("static_spawnpoint")) + or {x = 0, y = 2, z = 0} + + +-- return list of members as a table +local get_member_list = function(meta) + + return meta:get_string("members"):split(" ") +end + + +-- write member list table in protector meta as string +local set_member_list = function(meta, list) + + meta:set_string("members", table.concat(list, " ")) +end + + +-- check for owner name +local is_owner = function(meta, name) + + return name == meta:get_string("owner") +end + + +-- check for member name +local is_member = function (meta, name) + + for _, n in pairs(get_member_list(meta)) do + + if n == name then + return true + end + end + + return false +end + + +-- add player name to table as member +local add_member = function(meta, name) + + -- Constant (20) defined by player.h + if name:len() > 25 then + return + end + + -- does name already exist? + if is_owner(meta, name) + or is_member(meta, name) then + return + end + + local list = get_member_list(meta) + + if #list >= protector_max_share_count then + return + end + + table.insert(list, name) + + set_member_list(meta, list) +end + + +-- remove player name from table +local del_member = function(meta, name) + + local list = get_member_list(meta) + + for i, n in pairs(list) do + + if n == name then + table.remove(list, i) + break + end + end + + set_member_list(meta, list) +end + + +-- protector interface +local protector_formspec = function(meta) + + local formspec = "size[8,7]" + .. default.gui_bg + .. default.gui_bg_img + .. default.gui_slots + .. "label[2.5,0;" .. F(S("-- Protector interface --")) .. "]" + .. "label[0,1;" .. F(S("PUNCH node to show protected area")) .. "]" + .. "label[0,2;" .. F(S("Members:")) .. "]" + .. "button_exit[2.5,6.2;3,0.5;close_me;" .. F(S("Close")) .. "]" + .. "field_close_on_enter[protector_add_member;false]" + + local members = get_member_list(meta) + local npp = protector_max_share_count -- max users added to protector list + local i = 0 + + for n = 1, #members do + + if i < npp then + + -- show username + formspec = formspec .. "button[" .. (i % 4 * 2) + .. "," .. math.floor(i / 4 + 3) + .. ";1.5,.5;protector_member;" .. F(members[n]) .. "]" + + -- username remove button + .. "button[" .. (i % 4 * 2 + 1.25) .. "," + .. math.floor(i / 4 + 3) + .. ";.75,.5;protector_del_member_" .. F(members[n]) .. ";X]" + end + + i = i + 1 + end + + if i < npp then + + -- user name entry field + formspec = formspec .. "field[" .. (i % 4 * 2 + 1 / 3) .. "," + .. (math.floor(i / 4 + 3) + 1 / 3) + .. ";1.433,.5;protector_add_member;;]" + + -- username add button + .."button[" .. (i % 4 * 2 + 1.25) .. "," + .. math.floor(i / 4 + 3) .. ";.75,.5;protector_submit;+]" + + end + + return formspec +end + + +-- check if pos is inside a protected spawn area +local inside_spawn = function(pos, radius) + + if protector_spawn <= 0 then + return false + end + + if pos.x < statspawn.x + radius + and pos.x > statspawn.x - radius + and pos.y < statspawn.y + radius + and pos.y > statspawn.y - radius + and pos.z < statspawn.z + radius + and pos.z > statspawn.z - radius then + + return true + end + + return false +end + + +-- Infolevel: +-- 0 for no info +-- 1 for "This area is owned by !" if you can't dig +-- 2 for "This area is owned by . +-- 3 for checking protector overlaps + +protector.can_dig = function(r, pos, digger, onlyowner, infolevel) + + if not digger or not pos then + return false + end + + -- protector_bypass privileged users can override protection + if infolevel == 1 + and minetest.check_player_privs(digger, {protection_bypass = true}) then + return true + end + + -- infolevel 3 is only used to bypass priv check, change to 1 now + if infolevel == 3 then infolevel = 1 end + + -- is spawn area protected ? + if inside_spawn(pos, protector_spawn) then + + minetest.chat_send_player(digger, + S("Spawn @1 has been protected up to a @2 block radius.", + minetest.pos_to_string(statspawn), protector_spawn)) + + return false + end + + -- find the protector nodes + local pos = minetest.find_nodes_in_area( + {x = pos.x - r, y = pos.y - r, z = pos.z - r}, + {x = pos.x + r, y = pos.y + r, z = pos.z + r}, + {"protector:protect", "protector:protect2"}) + + local meta, owner, members + + for n = 1, #pos do + + meta = minetest.get_meta(pos[n]) + owner = meta:get_string("owner") or "" + members = meta:get_string("members") or "" + + -- node change and digger isn't owner + if infolevel == 1 and owner ~= digger then + + -- and you aren't on the member list + if onlyowner or not is_member(meta, digger) then + + minetest.chat_send_player(digger, + S("This area is owned by @1", owner) .. "!") + + return false + end + end + + -- when using protector as tool, show protector information + if infolevel == 2 then + + minetest.chat_send_player(digger, + S("This area is owned by @1", owner) .. ".") + + minetest.chat_send_player(digger, + S("Protection located at: @1", minetest.pos_to_string(pos[n]))) + + if members ~= "" then + + minetest.chat_send_player(digger, S("Members: @1.", members)) + end + + return false + end + + end + + -- show when you can build on unprotected area + if infolevel == 2 then + + if #pos < 1 then + + minetest.chat_send_player(digger, S("This area is not protected.")) + end + + minetest.chat_send_player(digger, S("You can build here.")) + end + + return true +end + + +local old_is_protected = minetest.is_protected + +-- check for protected area, return true if protected and digger isn't on list +function minetest.is_protected(pos, digger) + + digger = digger or "" -- nil check + + -- is area protected against digger? + if not protector.can_dig(protector_radius, pos, digger, false, 1) then + + local player = minetest.get_player_by_name(digger) + + if player and player:is_player() then + + -- hurt player if protection violated + if protector_hurt > 0 and player:get_hp() > 0 then + player:set_hp(player:get_hp() - protector_hurt) + end + + -- flip player when protection violated + if protector_flip then + + -- yaw + 180° + local yaw = player:get_look_horizontal() + math.pi + + if yaw > 2 * math.pi then + yaw = yaw - 2 * math.pi + end + + player:set_look_horizontal(yaw) + + -- invert pitch + player:set_look_vertical(-player:get_look_vertical()) + + -- if digging below player, move up to avoid falling through hole + local pla_pos = player:get_pos() + + if pos.y < pla_pos.y then + + player:set_pos({ + x = pla_pos.x, + y = pla_pos.y + 0.8, + z = pla_pos.z + }) + end + end + end + + return true + end + + -- otherwise can dig or place + return old_is_protected(pos, digger) +end + + +-- make sure protection block doesn't overlap another protector's area +local check_overlap = function(itemstack, placer, pointed_thing) + + if pointed_thing.type ~= "node" then + return itemstack + end + + local pos = pointed_thing.above + local name = placer:get_player_name() + + -- make sure protector doesn't overlap onto protected spawn area + if inside_spawn(pos, protector_spawn + protector_radius) then + + minetest.chat_send_player(name, + S("Spawn @1 has been protected up to a @2 block radius.", + minetest.pos_to_string(statspawn), protector_spawn)) + + return itemstack + end + + -- make sure protector doesn't overlap any other player's area + if not protector.can_dig(protector_radius * 2, pos, name, true, 3) then + + minetest.chat_send_player(name, + S("Overlaps into above players protected area")) + + return itemstack + end + + return minetest.item_place(itemstack, placer, pointed_thing) + +end + + +-- temporary pos store +local player_pos = {} + +-- protection node +minetest.register_node("protector:protect", { + description = "Protection Block" .. "\n" .. + "Swing me to see if what's pointed is protected!", + drawtype = "nodebox", + tiles = { + "ydecor_stone_rune.png", + "ydecor_stone_rune.png", + "ydecor_stone_rune.png^protector_logo.png" + }, + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2, unbreakable = 1}, + is_ground_content = false, + paramtype = "light", + light_source = 4, + + node_box = { + type = "fixed", + fixed = { + {-0.5 ,-0.5, -0.5, 0.5, 0.5, 0.5}, + } + }, + + on_place = check_overlap, + + 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", "Protection owned by @1!", meta:get_string("owner")) + meta:set_string("members", "") + end, + + on_use = function(itemstack, user, pointed_thing) + + if pointed_thing.type ~= "node" then + return + end + + protector.can_dig(protector_radius, pointed_thing.under, user:get_player_name(), false, 2) + end, + + on_rightclick = function(pos, node, clicker, itemstack) + + local meta = minetest.get_meta(pos) + local name = clicker:get_player_name() + + if meta + and protector.can_dig(1, pos, name, true, 1) then + + player_pos[name] = pos + + minetest.show_formspec(name, "protector:node", protector_formspec(meta)) + end + end, + + on_punch = function(pos, node, puncher) + + if minetest.is_protected(pos, puncher:get_player_name()) then + return + end + + minetest.add_entity(pos, "protector:display") + end, + + can_dig = function(pos, player) + + return player and protector.can_dig(1, pos, player:get_player_name(), true, 1) + end, + + on_blast = function() end, + + after_destruct = function(pos, oldnode) + local objects = minetest.get_objects_inside_radius(pos, 0.5) + for _, v in ipairs(objects) do + v:remove() + end + end, +}) + +minetest.register_craft({ + output = "protector:protect", + recipe = { + {"default:stone", "default:stone", "default:stone"}, + {"default:stone", "default:mese_crystal", "default:stone"}, + {"default:stone", "default:stone", "default:stone"}, + } +}) + + +-- protection logo +minetest.register_node("protector:protect2", { + description = S("Protection Logo") .. " (" .. S("USE for area check") .. ")", + tiles = {"protector_logo.png"}, + wield_image = "protector_logo.png", + inventory_image = "protector_logo.png", + sounds = default.node_sound_stone_defaults(), + groups = {dig_immediate = 2, unbreakable = 1}, + paramtype = "light", + paramtype2 = "wallmounted", + legacy_wallmounted = true, + light_source = 4, + drawtype = "nodebox", + sunlight_propagates = true, + walkable = true, + node_box = { + type = "wallmounted", + wall_top = {-0.375, 0.4375, -0.5, 0.375, 0.5, 0.5}, + wall_bottom = {-0.375, -0.5, -0.5, 0.375, -0.4375, 0.5}, + wall_side = {-0.5, -0.5, -0.375, -0.4375, 0.5, 0.375}, + }, + selection_box = {type = "wallmounted"}, + + on_place = check_overlap, + + 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", S("Protection (owned by @1)", meta:get_string("owner"))) + meta:set_string("members", "") + end, + + on_use = function(itemstack, user, pointed_thing) + + if pointed_thing.type ~= "node" then + return + end + + protector.can_dig(protector_radius, pointed_thing.under, user:get_player_name(), false, 2) + end, + + on_rightclick = function(pos, node, clicker, itemstack) + + local meta = minetest.get_meta(pos) + local name = clicker:get_player_name() + + if meta + and protector.can_dig(1, pos, name, true, 1) then + + player_pos[name] = pos + + minetest.show_formspec(name, "protector:node", protector_formspec(meta)) + end + end, + + on_punch = function(pos, node, puncher) + + if minetest.is_protected(pos, puncher:get_player_name()) then + return + end + + minetest.add_entity(pos, "protector:display") + end, + + can_dig = function(pos, player) + + return player and protector.can_dig(1, pos, player:get_player_name(), true, 1) + end, + + on_blast = function() end, + + after_destruct = function(pos, oldnode) + local objects = minetest.get_objects_inside_radius(pos, 0.5) + for _, v in ipairs(objects) do + v:remove() + end + end, +}) + +-- recipes to switch between protectors +minetest.register_craft({ + type = "shapeless", + output = "protector:protect", + recipe = {"protector:protect2"} +}) + +minetest.register_craft({ + type = "shapeless", + output = "protector:protect2", + recipe = {"protector:protect"} +}) + + +-- check formspec buttons or when name entered +minetest.register_on_player_receive_fields(function(player, formname, fields) + + if formname ~= "protector:node" then + return + end + + local name = player:get_player_name() + local pos = player_pos[name] + + if not name or not pos then + return + end + + local add_member_input = fields.protector_add_member + + -- reset formspec until close button pressed + if (fields.close_me or fields.quit) + and (not add_member_input or add_member_input == "") then + player_pos[name] = nil + return + end + + -- only owner can add names + if not protector.can_dig(1, pos, player:get_player_name(), true, 1) then + return + end + + -- are we adding member to a protection node ? (csm protection) + local nod = minetest.get_node(pos).name + + if nod ~= "protector:protect" + and nod ~= "protector:protect2" then + player_pos[name] = nil + return + end + + local meta = minetest.get_meta(pos) + + if not meta then + return + end + + -- add member [+] + if add_member_input then + + for _, i in pairs(add_member_input:split(" ")) do + add_member(meta, i) + end + end + + -- remove member [x] + for field, value in pairs(fields) do + + if string.sub(field, 0, + string.len("protector_del_member_")) == "protector_del_member_" then + + del_member(meta, + string.sub(field,string.len("protector_del_member_") + 1)) + end + end + + minetest.show_formspec(name, formname, protector_formspec(meta)) +end) + + +-- display entity shown when protector node is punched +minetest.register_entity("protector:display", { + physical = false, + collisionbox = {0, 0, 0, 0, 0, 0}, + visual = "wielditem", + -- wielditem seems to be scaled to 1.5 times original node size + visual_size = {x = 1.0 / 1.5, y = 1.0 / 1.5}, + textures = {"protector:display_node"}, + timer = 0, + + on_step = function(self, dtime) + + self.timer = self.timer + dtime + + -- remove after 5 seconds + if self.timer > 5 then + self.object:remove() + end + end, +}) + + +-- Display-zone node, Do NOT place the display as a node, +-- it is made to be used as an entity (see above) + +local x = protector_radius +minetest.register_node("protector:display_node", { + tiles = {"protector_display.png"}, + use_texture_alpha = true, + walkable = false, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + -- sides + {-(x+.55), -(x+.55), -(x+.55), -(x+.45), (x+.55), (x+.55)}, + {-(x+.55), -(x+.55), (x+.45), (x+.55), (x+.55), (x+.55)}, + {(x+.45), -(x+.55), -(x+.55), (x+.55), (x+.55), (x+.55)}, + {-(x+.55), -(x+.55), -(x+.55), (x+.55), (x+.55), -(x+.45)}, + -- top + {-(x+.55), (x+.45), -(x+.55), (x+.55), (x+.55), (x+.55)}, + -- bottom + {-(x+.55), -(x+.55), -(x+.55), (x+.55), -(x+.45), (x+.55)}, + -- middle (surround protector) + {-.55,-.55,-.55, .55,.55,.55}, + }, + }, + selection_box = { + type = "regular", + }, + paramtype = "light", + groups = {dig_immediate = 3, not_in_creative_inventory = 1}, + drop = "", +}) diff --git a/mods/protector/intllib.lua b/mods/protector/intllib.lua new file mode 100644 index 0000000..6669d72 --- /dev/null +++ b/mods/protector/intllib.lua @@ -0,0 +1,45 @@ + +-- Fallback functions for when `intllib` is not installed. +-- Code released under Unlicense . + +-- Get the latest version of this file at: +-- https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua + +local function format(str, ...) + local args = { ... } + local function repl(escape, open, num, close) + if escape == "" then + local replacement = tostring(args[tonumber(num)]) + if open == "" then + replacement = replacement..close + end + return replacement + else + return "@"..open..num..close + end + end + return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl)) +end + +local gettext, ngettext +if minetest.get_modpath("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + gettext, ngettext = intllib.make_gettext_pair() + else + -- Old method using text files. + gettext = intllib.Getter() + end +end + +-- Fill in missing functions. + +gettext = gettext or function(msgid, ...) + return format(msgid, ...) +end + +ngettext = ngettext or function(msgid, msgid_plural, n, ...) + return format(n==1 and msgid or msgid_plural, ...) +end + +return gettext, ngettext diff --git a/mods/protector/license.txt b/mods/protector/license.txt new file mode 100644 index 0000000..fec6f6a --- /dev/null +++ b/mods/protector/license.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 TenPlus1 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/mods/protector/locale/de.po b/mods/protector/locale/de.po new file mode 100644 index 0000000..5f8a695 --- /dev/null +++ b/mods/protector/locale/de.po @@ -0,0 +1,196 @@ +# German translation for PROTECTOR MOD. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the PROTECTOR MOD package. +# Xanthin , 2016. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +#, fuzzy +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "" +"Entferne Störschützer von bestimmten Namen in der Nähe von Spielern (trenne " +"Namen durch Leerzeichen)" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "Ersetze Besitzer der Störschützer mit neuem Besitzer" + +#: admin.lua +msgid " " +msgstr " " + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "Ersetze Besitzer der Störschützer von '@1' mit '@2'" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "Zeige geschützte Bereiche der Störschützer in der Nähe" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Störschutznamen zum Entfernen: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "Namensliste zurückgesetzt" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Geschützte Holztür" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Geschützte Stahltür" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Geschützte Falltür" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Geschützte Stahlfalltür" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Geschützte Truhe" + +#: doors_chest.lua +msgid "@1 moves stuff to protected chest at @2" +msgstr "@1 verlagert Dinge in geschützte Truhe bei @2" + +#: doors_chest.lua +msgid "@1 takes stuff from protected chest at @2" +msgstr "@1 nimmt Dinge aus geschützter Truhe bei @2" + +#: doors_chest.lua +msgid "@1 moves stuff inside protected chest at @2" +msgstr "@1 verschiebt Dinge innerhalb der geschützten Truhe bei @2" + +#: doors_chest.lua +msgid "To Chest" +msgstr "Zur Truhe" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "Zum Inventar" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Geschützte Truhe (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "-- Störschutz-Interface --" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "SCHLAGE Node, um geschützten Bereich anzuzeigen oder" + +#: init.lua +msgid "USE for area check" +msgstr "BENUTZE für Bereichsprüfung" + +#: init.lua +msgid "Members:" +msgstr "Mitglieder:" + +#: init.lua +msgid "Close" +msgstr "Schließen" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Störschutz befindet sich bei: @1" + +#: init.lua +msgid "Members: @1." +msgstr "Mitglieder: @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Dieser Bereich ist nicht geschützt." + +#: init.lua +msgid "You can build here." +msgstr "Du kannst hier bauen." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "Überlappung im geschützen Bereich eines Spielers" + +#: init.lua +msgid "Protection Block" +msgstr "Störschutzblock" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Störschutz (gehört @1)" + +#: init.lua +msgid "Protection Logo" +msgstr "Störschutzlogo" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Protector Redo geladen" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "Spawn @1 ist geschützt mit einem Radius von @2 Blöcke." + +#: init.lua +msgid "This area is owned by @1" +msgstr "Dieser Bereich gehört @1" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "on_punchplayer wurde durch \"nil objects\" aufgerufen" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "pvp_protect ist nicht aktiv, aktualisiere deine Minetestversion" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "pvp_protect ist ausgeschaltet" + +#: hud.lua +msgid "Owner: @1" +msgstr "Besitzer: @1" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" +"Störschutz Platzier-Werkzeug (stehe neben Störschutz, schaue in die " +"gewünschte Richtung und anwenden)" + +#: tool.lua +msgid "Protector already in place!" +msgstr "Störschutz is bereits platziert!" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "Keine Störschützer mehr im Inventar!" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Störschutz befindet sich bei: @1" diff --git a/mods/protector/locale/fr.po b/mods/protector/locale/fr.po new file mode 100644 index 0000000..c2fce21 --- /dev/null +++ b/mods/protector/locale/fr.po @@ -0,0 +1,198 @@ +# French translation for PROTECTOR MOD. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the PROTECTOR MOD package. +# Doloment, 2017. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +#, fuzzy +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "" +"Retirer les protecteurs près des joueurs avec les noms fournis (noms séparés " +"avec des espaces)" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "" + +#: admin.lua +msgid " " +msgstr "" + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Noms de protecteurs à supprimer: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "Liste de noms réinitialiser" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Porte en bois protégée" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Porte en acier protégée" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Trappe protégé" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Trap en acier protégé" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Coffre protégé" + +#: doors_chest.lua +msgid "@1 moves stuff to protected chest at @2" +msgstr "@1 déplace des objets vers le coffre protégée à @2" + +#: doors_chest.lua +msgid "@1 takes stuff from protected chest at @2" +msgstr "@1 prend des objets du coffre protégée à @2" + +#: doors_chest.lua +#, fuzzy +msgid "@1 moves stuff inside protected chest at @2" +msgstr "@1 déplace des objets à l'intérieur de du coffre protégé à @2" + +#: doors_chest.lua +msgid "To Chest" +msgstr "Vers le coffre" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "Vers l'inventaire" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Coffre protégé (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "-- Interface Protector --" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "TAPÉ le bloc pour afficher la zone protégée" + +#: init.lua +msgid "USE for area check" +msgstr "UTILISER pour vérifier la zone" + +#: init.lua +msgid "Members:" +msgstr "Membres:" + +#: init.lua +msgid "Close" +msgstr "Fermer" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Protection située à: @1" + +#: init.lua +msgid "Members: @1." +msgstr "Membres: @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Cette zone n'est pas protégée." + +#: init.lua +msgid "You can build here." +msgstr "Vous pouvez construire ici." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "Vous chevauché une zone protégé." + +#: init.lua +msgid "Protection Block" +msgstr "Bloc de protection" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Protection (détenue par @1)" + +#: init.lua +msgid "Protection Logo" +msgstr "Logo de protection" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Protector Redo chargé" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "" + +#: init.lua +#, fuzzy +msgid "This area is owned by @1" +msgstr "Cette zone appartient à @1!" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "[Protector] on_punchplayer appelé avec des objets nil" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "" +"[Protector] pvp_protect est désactivé, mettez à jour votre version de " +"Minetest" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "[Protector] pvp_protect est désactivé" + +#: hud.lua +msgid "Owner: @1" +msgstr "" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" + +#: tool.lua +msgid "Protector already in place!" +msgstr "" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Protection située à: @1" diff --git a/mods/protector/locale/ru.po b/mods/protector/locale/ru.po new file mode 100644 index 0000000..149082f --- /dev/null +++ b/mods/protector/locale/ru.po @@ -0,0 +1,197 @@ +# Russian translation for PROTECTOR MOD. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the PROTECTOR MOD package. +# Doloment, 2017. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +#, fuzzy +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "" +"Удалить защиту рядом с игроками (перечислить имена, разделяя пробелами)" + +#: admin.lua +msgid "" +msgstr "<список имён>" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "Заменить владельца защиты новым владельцем" + +#: admin.lua +msgid " " +msgstr "<имя владельца> <имя нового владельца>" + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "Заменяется владелец защиты с '@1' на '@2'" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "Показать защищенные территории с ближней защитой" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Имена защит, подлежащих удалению: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "Сброс списка имен" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Защищенная яблоневая дверь" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Защищенная стальная дверь" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Защищенный яблоневый люк" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Защищенный стальной люк" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Защищенный сундук" + +#: doors_chest.lua +msgid "@1 moves stuff to protected chest at @2" +msgstr "@1 перемещает вещи в защищенный сундук на координатах @2" + +#: doors_chest.lua +msgid "@1 takes stuff from protected chest at @2" +msgstr "@1 берет вещи из защищенного сундука на координатах @2" + +#: doors_chest.lua +msgid "@1 moves stuff inside protected chest at @2" +msgstr "@1 перемещает вещи внутри защищенного сундука на координатах @2" + +#: doors_chest.lua +msgid "To Chest" +msgstr "В сундук" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "В инвентрарь" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Защищенный сундук (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "-- Настройка защиты --" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "СТУКНУТЬ узел для подсведки защищенной территории" + +#: init.lua +msgid "USE for area check" +msgstr "ЛКМ для проверки защищенной территории" + +#: init.lua +msgid "Members:" +msgstr "Участники:" + +#: init.lua +msgid "Close" +msgstr "Закрыть" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Защита находится на координатах @1" + +#: init.lua +msgid "Members: @1." +msgstr "Участники: @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Территория свободна." + +#: init.lua +msgid "You can build here." +msgstr "Здесь можно ставить блоки." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "" +"Защитный блок не может быть установлен: пересечение с областями, защищенными " +"другими игроками" + +#: init.lua +msgid "Protection Block" +msgstr "Защитный блок" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Защита игрока @1" + +#: init.lua +msgid "Protection Logo" +msgstr "Защитный знак" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Модификация \"Переделанная Защита\" загружена" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "Спаун @1 защищен в радиусе @2 блока." + +#: init.lua +msgid "This area is owned by @1" +msgstr "Эта территория пренадлежит @1" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "[Защита] on_punchplayer вызвана с нулевыми объектами" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "[Защита] pvp_protect не активен, обновите версию Minetest" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "[Защита] pvp_protect отключен" + +#: hud.lua +msgid "Owner: @1" +msgstr "Владелец: @1" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" +"Инструмент установки защиты (станьте рядом с защитой, повернитесь в нужное " +"направление и используйте)" + +#: tool.lua +msgid "Protector already in place!" +msgstr "Защита уже установлена!" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "У вас нет защитных блоков в инвентаре!" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Защита находится на координатах @1" diff --git a/mods/protector/locale/template.pot b/mods/protector/locale/template.pot new file mode 100644 index 0000000..f8e095b --- /dev/null +++ b/mods/protector/locale/template.pot @@ -0,0 +1,191 @@ +# Template for PROTECTOR MOD. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the PROTECTOR MOD package. +# Xanthin , 2016. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "" + +#: admin.lua +msgid " " +msgstr "" + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "" + +#: admin.lua +msgid "Name List Reset" +msgstr "" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "" + +#: doors_chest.lua +msgid "@1 moves stuff to protected chest at @2" +msgstr "" + +#: doors_chest.lua +msgid "@1 takes stuff from protected chest at @2" +msgstr "" + +#: doors_chest.lua +msgid "@1 moves stuff inside protected chest at @2" +msgstr "" + +#: doors_chest.lua +msgid "To Chest" +msgstr "" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "" + +#: init.lua +msgid "-- Protector interface --" +msgstr "" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "" + +#: init.lua +msgid "USE for area check" +msgstr "" + +#: init.lua +msgid "Members:" +msgstr "" + +#: init.lua +msgid "Close" +msgstr "" + +#: init.lua +msgid "Protection located at: @1" +msgstr "" + +#: init.lua +msgid "Members: @1." +msgstr "" + +#: init.lua +msgid "This area is not protected." +msgstr "" + +#: init.lua +msgid "You can build here." +msgstr "" + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "" + +#: init.lua +msgid "Protection Block" +msgstr "" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "" + +#: init.lua +msgid "Protection Logo" +msgstr "" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "" + +#: init.lua +msgid "This area is owned by @1" +msgstr "" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "" + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "" + +#: hud.lua +msgid "Owner: @1" +msgstr "" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" + +#: tool.lua +msgid "Protector already in place!" +msgstr "" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "" diff --git a/mods/protector/locale/tr.po b/mods/protector/locale/tr.po new file mode 100644 index 0000000..d77f9c0 --- /dev/null +++ b/mods/protector/locale/tr.po @@ -0,0 +1,195 @@ +# Turkish translation for PROTECTOR MOD. +# Copyright (C) 2018 TenPlus1 +# This file is distributed under the same license as the PROTECTOR MOD package. +# mahmutelmas06, 2016. +# CodeXP , 2018. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROTECTOR MOD\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-07-10 17:33+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: CodeXP \n" +"Language-Team: \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: admin.lua +#, fuzzy +msgid "Remove Protectors around players (separate names with spaces)" +msgstr "" +"Ismi verilen oyuncuların yanındaki korumaları kaldır. (İsimleri boşlukla " +"ayır)" + +#: admin.lua +msgid "" +msgstr "" + +#: admin.lua +msgid "Replace Protector Owner with name provided" +msgstr "" + +#: admin.lua +msgid " " +msgstr "" + +#: admin.lua +msgid "Replacing Protector name '@1' with '@2'" +msgstr "" + +#: admin.lua +msgid "Show protected areas of your nearby protectors" +msgstr "" + +#: admin.lua +msgid "Protector Names to remove: @1" +msgstr "Silinecek korumaların isimleri: @1" + +#: admin.lua +msgid "Name List Reset" +msgstr "İsim listesini sıfırla" + +#: doors_chest.lua +msgid "Protected Wooden Door" +msgstr "Korumalı ahşap kapı" + +#: doors_chest.lua +msgid "Protected Steel Door" +msgstr "Korumalı çelik kapı" + +#: doors_chest.lua +msgid "Protected Trapdoor" +msgstr "Korumalı tuzak kapısı" + +#: doors_chest.lua +msgid "Protected Steel Trapdoor" +msgstr "Korumalı çelik tuzak kapısı" + +#: doors_chest.lua +msgid "Protected Chest" +msgstr "Korumalı sandık" + +#: doors_chest.lua +msgid "@1 moves stuff to protected chest at @2" +msgstr "@1 korumalı sandığa birşeyler koydu @2" + +#: doors_chest.lua +msgid "@1 takes stuff from protected chest at @2" +msgstr "@1 korumalı sandıktan birşeyler aldı @2" + +#: doors_chest.lua +#, fuzzy +msgid "@1 moves stuff inside protected chest at @2" +msgstr "@1 korumalı sandığa içinde bir şeyler taşındı @2" + +#: doors_chest.lua +msgid "To Chest" +msgstr "Sandığa" + +#: doors_chest.lua +msgid "To Inventory" +msgstr "Envantere" + +#: doors_chest.lua +msgid "Protected Chest (@1)" +msgstr "Korumalı sandık (@1)" + +#: init.lua +msgid "-- Protector interface --" +msgstr "" + +#: init.lua +msgid "PUNCH node to show protected area" +msgstr "Korunan alanı göstermek için yumruk" + +#: init.lua +msgid "USE for area check" +msgstr "Bölge kontrolü için kullan" + +#: init.lua +msgid "Members:" +msgstr "Üyeler" + +#: init.lua +msgid "Close" +msgstr "Kapat" + +#: init.lua +msgid "Protection located at: @1" +msgstr "Korumanın bulunduğu yer @1" + +#: init.lua +msgid "Members: @1." +msgstr "Üyeler @1." + +#: init.lua +msgid "This area is not protected." +msgstr "Bu alan korumalı değildir." + +#: init.lua +msgid "You can build here." +msgstr "Buraya inşaa edebilirsiniz." + +#: init.lua tool.lua +msgid "Overlaps into above players protected area" +msgstr "" + +#: init.lua +msgid "Protection Block" +msgstr "Koruma kutusu" + +#: admin.lua init.lua tool.lua +msgid "Protection (owned by @1)" +msgstr "Koruma (@1 sahibidir)" + +#: init.lua +msgid "Protection Logo" +msgstr "Koruma arması" + +#: init.lua +msgid "[MOD] Protector Redo loaded" +msgstr "[MOD] Protector Redo yüklendi" + +#: init.lua +msgid "Spawn @1 has been protected up to a @2 block radius." +msgstr "" + +#: init.lua +msgid "This area is owned by @1" +msgstr "Burasının sahibi @1!" + +#: pvp.lua +msgid "[Protector] on_punchplayer called with nil objects" +msgstr "[Protector] on_punchplayer boş objelerle çağrıldı" + +#: pvp.lua +msgid "[Protector] pvp_protect not active, update your version of Minetest" +msgstr "[Protector] pvp_protect aktif değil, Minetest sürümünüzü güncelleyin." + +#: pvp.lua +msgid "[Protector] pvp_protect is disabled" +msgstr "[Protector] pvp_protect kapatıldı." + +#: hud.lua +msgid "Owner: @1" +msgstr "" + +#: tool.lua +msgid "Protector Placer Tool (stand near protector, face direction and use)" +msgstr "" + +#: tool.lua +msgid "Protector already in place!" +msgstr "" + +#: tool.lua +msgid "No protectors available to place!" +msgstr "" + +#: tool.lua +msgid "Protector placed at @1" +msgstr "Korumanın bulunduğu yer @1" diff --git a/mods/protector/lucky_block.lua b/mods/protector/lucky_block.lua new file mode 100644 index 0000000..59c52c1 --- /dev/null +++ b/mods/protector/lucky_block.lua @@ -0,0 +1,18 @@ + +-- add lucky blocks + +if minetest.get_modpath("lucky_block") then + + lucky_block:add_blocks({ + {"dro", {"protector:protect"}, 3}, + {"dro", {"protector:protect2"}, 3}, + {"dro", {"protector:door_wood"}, 1}, + {"dro", {"protector:door_steel"}, 1}, + {"exp", 5, true}, + {"dro", {"protector:trapdoor"}, 1}, + {"dro", {"protector:trapdoor_steel"}, 1}, + {"dro", {"protector:tool"}, 1}, + {"dro", {"protector:chest"}, 1}, + {"exp"}, + }) +end diff --git a/mods/protector/mod.conf b/mods/protector/mod.conf new file mode 100644 index 0000000..8eb0aa8 --- /dev/null +++ b/mods/protector/mod.conf @@ -0,0 +1 @@ +name = protector \ No newline at end of file diff --git a/mods/protector/pvp.lua b/mods/protector/pvp.lua new file mode 100644 index 0000000..0efb62a --- /dev/null +++ b/mods/protector/pvp.lua @@ -0,0 +1,72 @@ + +local S = protector.intllib + +-- get static spawn position +local statspawn = minetest.string_to_pos(minetest.settings:get("static_spawnpoint")) + or {x = 0, y = 2, z = 0} + +-- is spawn protected +local protector_spawn = tonumber(minetest.settings:get("protector_spawn") + or minetest.settings:get("protector_pvp_spawn")) or 0 + +-- is night-only pvp enabled +local protector_night_pvp = minetest.settings:get_bool("protector_night_pvp") + +-- disables PVP in your own protected areas +if minetest.settings:get_bool("enable_pvp") +and minetest.settings:get_bool("protector_pvp") then + + if minetest.register_on_punchplayer then + + minetest.register_on_punchplayer(function(player, hitter, + time_from_last_punch, tool_capabilities, dir, damage) + + if not player + or not hitter then + print(S("[Protector] on_punchplayer called with nil objects")) + end + + if not hitter:is_player() then + return false + end + + -- no pvp at spawn area + local pos = player:get_pos() + + if pos.x < statspawn.x + protector_spawn + and pos.x > statspawn.x - protector_spawn + and pos.y < statspawn.y + protector_spawn + and pos.y > statspawn.y - protector_spawn + and pos.z < statspawn.z + protector_spawn + and pos.z > statspawn.z - protector_spawn then + return true + end + + -- do we enable pvp at night time only ? + if protector_night_pvp then + + -- get time of day + local tod = minetest.get_timeofday() or 0 + + if tod > 0.2 and tod < 0.8 then + -- + else + return false + end + end + + -- is player being punched inside a protected area ? + if minetest.is_protected(pos, hitter:get_player_name()) then + return true + end + + return false + + end) + else + print(S("[Protector] pvp_protect not active, update your version of Minetest")) + + end +else + print(S("[Protector] pvp_protect is disabled")) +end diff --git a/mods/protector/screenshot.png b/mods/protector/screenshot.png new file mode 100644 index 0000000..641c5f2 Binary files /dev/null and b/mods/protector/screenshot.png differ diff --git a/mods/protector/textures/license.txt b/mods/protector/textures/license.txt new file mode 100644 index 0000000..8798df4 --- /dev/null +++ b/mods/protector/textures/license.txt @@ -0,0 +1,30 @@ + +following Textures created by Fernando Zapata (CC BY-SA 3.0): + doors_wood.png + doors_wood_a.png + doors_wood_b.png + doors_brown.png + +following Textures created by BlockMen (WTFPL): + doors_trapdoor.png + +following textures created by celeron55 (CC BY-SA 3.0): + doors_trapdoor_side.png + +following textures created by PilzAdam (WTFPL): + doors_steel.png + doors_steel_a.png + doors_steel_b.png + doors_grey.png + doors_trapdoor_steel.png + doors_trapdoor_steel_side.png + +following textures by Cisoun (WTFPL): + default_chest_front.png + default_chest_side.png + default_chest_top.png + +following textures by TenPlus1 (CC BY-SA 3.0): + protector_logo.png + protector_display.png + protector_overlay.png diff --git a/mods/protector/textures/protector_display.png b/mods/protector/textures/protector_display.png new file mode 100644 index 0000000..6d7ec7d Binary files /dev/null and b/mods/protector/textures/protector_display.png differ diff --git a/mods/protector/textures/protector_logo.png b/mods/protector/textures/protector_logo.png new file mode 100644 index 0000000..c6f6f51 Binary files /dev/null and b/mods/protector/textures/protector_logo.png differ diff --git a/mods/protector/textures/protector_overlay.png b/mods/protector/textures/protector_overlay.png new file mode 100644 index 0000000..00261da Binary files /dev/null and b/mods/protector/textures/protector_overlay.png differ diff --git a/mods/protector/tool.lua b/mods/protector/tool.lua new file mode 100644 index 0000000..6171e2f --- /dev/null +++ b/mods/protector/tool.lua @@ -0,0 +1,126 @@ + +-- protector placement tool (thanks to Shara for code and idea) + +-- get protection radius +local r = tonumber(minetest.settings:get("protector_radius")) or 5 + +minetest.register_craftitem("protector:tool", { + description = "Protector Placer Tool (stand near protector, face direction and use)", + inventory_image = "protector_display.png^protector_logo.png", + stack_max = 1, + + on_use = function(itemstack, user, pointed_thing) + + local name = user:get_player_name() + + -- check for protector near player (2 block radius) + local pos = user:get_pos() + local pp = minetest.find_nodes_in_area( + vector.subtract(pos, 2), vector.add(pos, 2), + {"protector:protect", "protector:protect2"}) + + if #pp == 0 then return end -- none found + + pos = pp[1] -- take position of first protector found + + -- get members on protector + local meta = minetest.get_meta(pos) + local members = meta:get_string("members") or "" + + -- get direction player is facing + local dir = minetest.dir_to_facedir( user:get_look_dir() ) + local vec = {x = 0, y = 0, z = 0} + local gap = (r * 2) + 1 + local pit = user:get_look_pitch() + + -- set placement coords + if pit > 1.2 then + vec.y = gap -- up + elseif pit < -1.2 then + vec.y = -gap -- down + elseif dir == 0 then + vec.z = gap -- north + elseif dir == 1 then + vec.x = gap -- east + elseif dir == 2 then + vec.z = -gap -- south + elseif dir == 3 then + vec.x = -gap -- west + end + + -- new position + pos.x = pos.x + vec.x + pos.y = pos.y + vec.y + pos.z = pos.z + vec.z + + -- does placing a protector overlap existing area + if not protector.can_dig(r * 2, pos, user:get_player_name(), true, 3) then + + minetest.chat_send_player(name, + "Overlaps into above players protected area") + + return + end + + -- does a protector already exist ? + if #minetest.find_nodes_in_area( + vector.subtract(pos, 1), vector.add(pos, 1), + {"protector:protect", "protector:protect2"}) > 0 then + + minetest.chat_send_player(name, "Protector already in place!") + return + end + + -- do we have protectors to use ? + local nod + local inv = user:get_inventory() + + if not inv:contains_item("main", "protector:protect") + and not inv:contains_item("main", "protector:protect2") then + minetest.chat_send_player(name, "No protectors available to place!") + return + end + + -- take protector (block first then logo) + if inv:contains_item("main", "protector:protect") then + + inv:remove_item("main", "protector:protect") + nod = "protector:protect" + + elseif inv:contains_item("main", "protector:protect2") then + + inv:remove_item("main", "protector:protect2") + nod = "protector:protect2" + end + + -- place protector + minetest.set_node(pos, {name = nod, param2 = 1}) + + -- set protector metadata + local meta = minetest.get_meta(pos) + + meta:set_string("owner", name) + meta:set_string("infotext", "Protection (owned by " .. name .. ")") + + -- copy members across if holding sneak when using tool + if user:get_player_control().sneak then + meta:set_string("members", members) + else + meta:set_string("members", "") + end + + minetest.chat_send_player(name, + "Protector placed at " .. minetest.pos_to_string(pos)) + + end, +}) + +-- tool recipe +minetest.register_craft({ + output = "protector:tool", + recipe = { + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "protector:protect", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + } +}) diff --git a/mods/screwdriver/README.txt b/mods/screwdriver/README.txt new file mode 100644 index 0000000..14c073e --- /dev/null +++ b/mods/screwdriver/README.txt @@ -0,0 +1,13 @@ +Minetest Game mod: screwdriver +============================== +See license.txt for license information. + +License of source code +---------------------- +Originally by RealBadAngel, Maciej Kasatkin (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +License of media (textures) +--------------------------- +Created by Gambit (CC BY-SA 3.0): + screwdriver.png diff --git a/mods/screwdriver/init.lua b/mods/screwdriver/init.lua new file mode 100644 index 0000000..7fe64a6 --- /dev/null +++ b/mods/screwdriver/init.lua @@ -0,0 +1,172 @@ +screwdriver = {} + +screwdriver.ROTATE_FACE = 1 +screwdriver.ROTATE_AXIS = 2 +screwdriver.disallow = function(pos, node, user, mode, new_param2) + return false +end +screwdriver.rotate_simple = function(pos, node, user, mode, new_param2) + if mode ~= screwdriver.ROTATE_FACE then + return false + 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 + return + end + + local pos = pointed_thing.under + local player_name = user and user:get_player_name() or "" + + if minetest.is_protected(pos, player_name) then + minetest.record_protection_violation(pos, player_name) + return + end + + local node = minetest.get_node(pos) + local ndef = minetest.registered_nodes[node.name] + if not ndef then + return itemstack + end + -- can we rotate this paramtype2? + local fn = screwdriver.rotate[ndef.paramtype2] + if not fn and not ndef.on_rotate then + return itemstack + end + + local should_rotate = true + local new_param2 + if fn then + new_param2 = fn(pos, node, mode) + else + new_param2 = node.param2 + end + + -- 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 itemstack + elseif result == true then + should_rotate = false + 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 and new_param2 ~= node.param2 then + node.param2 = new_param2 + minetest.swap_node(pos, node) + minetest.check_for_falling(pos) + end + + if not (creative and creative.is_enabled_for and + creative.is_enabled_for(player_name)) then + itemstack:add_wear(65535 / ((uses or 200) - 1)) + end + + return itemstack +end + +-- Screwdriver +minetest.register_tool("screwdriver:screwdriver", { + description = "Screwdriver (left-click rotates face, right-click rotates axis)", + inventory_image = "screwdriver.png", + groups = {tool = 1}, + on_use = function(itemstack, user, pointed_thing) + screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE, 200) + return itemstack + end, + on_place = function(itemstack, user, pointed_thing) + screwdriver.handler(itemstack, user, pointed_thing, screwdriver.ROTATE_AXIS, 200) + return itemstack + end, +}) + + +minetest.register_craft({ + output = "screwdriver:screwdriver", + recipe = { + {"default:steel_ingot"}, + {"group:stick"} + } +}) + +minetest.register_alias("screwdriver:screwdriver1", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver2", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver3", "screwdriver:screwdriver") +minetest.register_alias("screwdriver:screwdriver4", "screwdriver:screwdriver") diff --git a/mods/screwdriver/license.txt b/mods/screwdriver/license.txt new file mode 100644 index 0000000..d9b721b --- /dev/null +++ b/mods/screwdriver/license.txt @@ -0,0 +1,50 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2013-2016 RealBadAngel, Maciej Kasatkin +Copyright (C) 2013-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) 2013-2016 Gambit + +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/screwdriver/textures/screwdriver.png b/mods/screwdriver/textures/screwdriver.png new file mode 100644 index 0000000..b2a56d5 Binary files /dev/null and b/mods/screwdriver/textures/screwdriver.png differ diff --git a/mods/sfinv/README.txt b/mods/sfinv/README.txt new file mode 100644 index 0000000..a7ac794 --- /dev/null +++ b/mods/sfinv/README.txt @@ -0,0 +1,13 @@ +Minetest Game mod: sfinv +======================== +See license.txt for license information. + +Simple Fast Inventory. +A cleaner, simpler, solution to having an advanced inventory in Minetest. +See game_api.txt for this mod's API. +Available for use outside of MTG here: +https://forum.minetest.net/viewtopic.php?t=19765 + +Authors of source code +---------------------- +rubenwardy (MIT) diff --git a/mods/sfinv/api.lua b/mods/sfinv/api.lua new file mode 100644 index 0000000..b9ddb39 --- /dev/null +++ b/mods/sfinv/api.lua @@ -0,0 +1,178 @@ +sfinv = { + pages = {}, + pages_unordered = {}, + contexts = {}, + enabled = true +} + +function sfinv.register_page(name, def) + assert(name, "Invalid sfinv page. Requires a name") + assert(def, "Invalid sfinv page. Requires a def[inition] table") + assert(def.get, "Invalid sfinv page. Def requires a get function.") + assert(not sfinv.pages[name], "Attempt to register already registered sfinv page " .. dump(name)) + + sfinv.pages[name] = def + def.name = name + table.insert(sfinv.pages_unordered, def) +end + +function sfinv.override_page(name, def) + assert(name, "Invalid sfinv page override. Requires a name") + assert(def, "Invalid sfinv page override. Requires a def[inition] table") + local page = sfinv.pages[name] + assert(page, "Attempt to override sfinv page " .. dump(name) .. " which does not exist.") + for key, value in pairs(def) do + page[key] = value + end +end + +function sfinv.get_nav_fs(player, context, nav, current_idx) + -- Only show tabs if there is more than one page + if #nav > 1 then + return "tabheader[0,0;sfinv_nav_tabs;" .. table.concat(nav, ",") .. + ";" .. current_idx .. ";true;false]" + else + return "" + end +end + +local theme_inv = [[ + list[current_player;main;0,4.7;8,1;] + list[current_player;main;0,5.85;8,3;8] + ]] + +function sfinv.make_formspec(player, context, content, show_inv, size) + local tmp = { + size or "size[8,8.6]", + sfinv.get_nav_fs(player, context, context.nav_titles, context.nav_idx), + content + } + if show_inv then + tmp[#tmp + 1] = theme_inv + end + return table.concat(tmp, "") +end + +function sfinv.get_homepage_name(player) + return "sfinv:crafting" +end + +function sfinv.get_formspec(player, context) + -- Generate navigation tabs + local nav = {} + local nav_ids = {} + local current_idx = 1 + for i, pdef in pairs(sfinv.pages_unordered) do + if not pdef.is_in_nav or pdef:is_in_nav(player, context) then + nav[#nav + 1] = pdef.title + nav_ids[#nav_ids + 1] = pdef.name + if pdef.name == context.page then + current_idx = #nav_ids + end + end + end + context.nav = nav_ids + context.nav_titles = nav + context.nav_idx = current_idx + + -- Generate formspec + local page = sfinv.pages[context.page] or sfinv.pages["404"] + if page then + return page:get(player, context) + else + local old_page = context.page + local home_page = sfinv.get_homepage_name(player) + + if old_page == home_page then + minetest.log("error", "[sfinv] Couldn't find " .. dump(old_page) .. + ", which is also the old page") + + return "" + end + + context.page = home_page + assert(sfinv.pages[context.page], "[sfinv] Invalid homepage") + minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. + " so switching to homepage") + + return sfinv.get_formspec(player, context) + end +end + +function sfinv.get_or_create_context(player) + local name = player:get_player_name() + local context = sfinv.contexts[name] + if not context then + context = { + page = sfinv.get_homepage_name(player) + } + sfinv.contexts[name] = context + end + return context +end + +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 + sfinv.set_player_inventory_formspec(player) + end +end) + +minetest.register_on_leaveplayer(function(player) + sfinv.contexts[player:get_player_name()] = nil +end) + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname ~= "" or not sfinv.enabled then + return false + end + + -- Get Context + local name = player:get_player_name() + local context = sfinv.contexts[name] + if not context then + sfinv.set_player_inventory_formspec(player) + return false + end + + -- Was a tab selected? + if fields.sfinv_nav_tabs and context.nav then + local tid = tonumber(fields.sfinv_nav_tabs) + if tid and tid > 0 then + local id = context.nav[tid] + local page = sfinv.pages[id] + if id and page then + sfinv.set_page(player, id) + end + end + 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/sfinv/init.lua b/mods/sfinv/init.lua new file mode 100644 index 0000000..cfb664f --- /dev/null +++ b/mods/sfinv/init.lua @@ -0,0 +1 @@ +--dofile(minetest.get_modpath("sfinv") .. "/api.lua") diff --git a/mods/sfinv/license.txt b/mods/sfinv/license.txt new file mode 100644 index 0000000..e27dc85 --- /dev/null +++ b/mods/sfinv/license.txt @@ -0,0 +1,24 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2016-2018 rubenwardy + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT diff --git a/mods/shields/LICENSE.txt b/mods/shields/LICENSE.txt new file mode 100644 index 0000000..316bc89 --- /dev/null +++ b/mods/shields/LICENSE.txt @@ -0,0 +1,8 @@ +[mod] Shields [shields] +======================= + +License Source Code: Copyright (C) 2013-2017 Stuart Jones - LGPL v2.1 + +License Textures: Copyright (C) 2017 davidthecreator - CC-BY-SA 3.0 + +https://github.com/daviddoesminetest/3d-armors-new-textures diff --git a/mods/shields/README.txt b/mods/shields/README.txt new file mode 100644 index 0000000..5a72097 --- /dev/null +++ b/mods/shields/README.txt @@ -0,0 +1,16 @@ +[mod] Shields [shields] +======================= + +Adds shields to 3d_armor + +Depends: 3d_armor + +Originally a part of 3d_armor, shields have been re-included as an optional extra. +If you do not what shields then simply remove the shields folder from the modpack. + +Shields Configuration +--------------------- + +Override the following default settings by adding them to your minetest.conf file. + +shields_disable_sounds = false diff --git a/mods/shields/crafting_guide.txt b/mods/shields/crafting_guide.txt new file mode 100644 index 0000000..9b61dde --- /dev/null +++ b/mods/shields/crafting_guide.txt @@ -0,0 +1,36 @@ +Shields -- Crafting Guide +-------------------------- + ++---+---+---+ +| X | X | X | ++---+---+---+ +| X | X | X | ++---+---+---+ +| | X | | ++---+---+---+ + +[shields:shield_wood] X = [default:wood] +[shields:shield_cactus] X = [default:cactus] +[shields:shield_steel] X = [default:steel_ingot] +[shields:shield_bronze] X = [default:bronze_ingot] +[shields:shield_diamond] X = [default:diamond] +[shields:shield_gold] X = [default:gold_ingot] +[shields:shield_mithril] X = [moreores:mithril_ingot] +[shields:shield_crystal] X = [ethereal:crystal_ingot] + +Enhanced Shields +---------------- + ++---+ +| S | ++---+ +| X | ++---+ +| S | ++---+ + +[shields:shield_enhanced_wood] X = [shields:shield_wood] +[shields:shield_enhanced_cactus] X = [shields:shield_cactus] + +S = [default:steel_ingot] + diff --git a/mods/shields/depends.txt b/mods/shields/depends.txt new file mode 100644 index 0000000..585cc7a --- /dev/null +++ b/mods/shields/depends.txt @@ -0,0 +1,2 @@ +default +3d_armor diff --git a/mods/shields/description.txt b/mods/shields/description.txt new file mode 100644 index 0000000..cb378bb --- /dev/null +++ b/mods/shields/description.txt @@ -0,0 +1 @@ +Adds visible shields to 3d armor. diff --git a/mods/shields/init.lua b/mods/shields/init.lua new file mode 100644 index 0000000..ad3ff9a --- /dev/null +++ b/mods/shields/init.lua @@ -0,0 +1,235 @@ +local S = function(s) return s end +if minetest.global_exists("intllib") then + if intllib.make_gettext_pair then + -- New method using gettext. + S = intllib.make_gettext_pair() + else + -- Old method using text files. + S = intllib.Getter() + end +end + +local disable_sounds = minetest.settings:get_bool("shields_disable_sounds") +local use_moreores = minetest.get_modpath("moreores") +local function play_sound_effect(player, name) + if not disable_sounds and player then + local pos = player:getpos() + if pos then + minetest.sound_play(name, { + pos = pos, + max_hear_distance = 10, + gain = 0.5, + }) + end + end +end + +if minetest.global_exists("armor") and armor.elements then + table.insert(armor.elements, "shield") + local mult = armor.config.level_multiplier or 1 + armor.config.level_multiplier = mult * 0.9 +end + +-- Regisiter Shields +--[[ +armor:register_armor("shields:shield_admin", { + description = S("Admin Shield"), + inventory_image = "shields_inv_shield_admin.png", + groups = {armor_shield=1000, armor_heal=100, armor_use=0, not_in_creative_inventory=1}, +}) + +minetest.register_alias("adminshield", "shields:shield_admin") +--]] +if armor.materials.wood then + armor:register_armor("shields:shield_wood", { + description = S("Wooden Shield"), + inventory_image = "shields_inv_shield_wood.png", + groups = {armor_shield=1, armor_heal=0, armor_use=2000, flammable=1}, + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=1}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_wood_footstep") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_wood_footstep") + end, + }) + armor:register_armor("shields:shield_enhanced_wood", { + description = S("Enhanced Wood Shield"), + inventory_image = "shields_inv_shield_enhanced_wood.png", + groups = {armor_shield=1, armor_heal=0, armor_use=2000}, + armor_groups = {fleshy=8}, + damage_groups = {cracky=3, snappy=2, choppy=3, crumbly=2, level=2}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_dig_metal") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_dug_metal") + end, + }) + minetest.register_craft({ + output = "shields:shield_enhanced_wood", + recipe = { + {"default:steel_ingot"}, + {"shields:shield_wood"}, + {"default:steel_ingot"}, + }, + }) +end + +if armor.materials.cactus then + armor:register_armor("shields:shield_cactus", { + description = S("Cactus Shield"), + inventory_image = "shields_inv_shield_cactus.png", + groups = {armor_shield=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=5}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=1}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_wood_footstep") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_wood_footstep") + end, + }) + armor:register_armor("shields:shield_enhanced_cactus", { + description = S("Enhanced Cactus Shield"), + inventory_image = "shields_inv_shield_enhanced_cactus.png", + groups = {armor_shield=1, armor_heal=0, armor_use=1000}, + armor_groups = {fleshy=8}, + damage_groups = {cracky=3, snappy=3, choppy=2, crumbly=2, level=2}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_dig_metal") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_dug_metal") + end, + }) + minetest.register_craft({ + output = "shields:shield_enhanced_cactus", + recipe = { + {"default:steel_ingot"}, + {"shields:shield_cactus"}, + {"default:steel_ingot"}, + }, + }) +end + +if armor.materials.steel then + armor:register_armor("shields:shield_steel", { + description = S("Steel Shield"), + inventory_image = "shields_inv_shield_steel.png", + groups = {armor_shield=1, armor_heal=0, armor_use=800, + physics_speed=-0.03, physics_gravity=0.03}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_dig_metal") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_dug_metal") + end, + }) +end + +if armor.materials.bronze then + armor:register_armor("shields:shield_bronze", { + description = S("Bronze Shield"), + inventory_image = "shields_inv_shield_bronze.png", + groups = {armor_shield=1, armor_heal=6, armor_use=400, + physics_speed=-0.03, physics_gravity=0.03}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=2, snappy=3, choppy=2, crumbly=1, level=2}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_dig_metal") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_dug_metal") + end, + }) +end + +if armor.materials.diamond then + armor:register_armor("shields:shield_diamond", { + description = S("Diamond Shield"), + inventory_image = "shields_inv_shield_diamond.png", + groups = {armor_shield=1, armor_heal=12, armor_use=200}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, choppy=1, level=3}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_glass_footstep") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_break_glass") + end, + }) +end + +if armor.materials.gold then + armor:register_armor("shields:shield_gold", { + description = S("Gold Shield"), + inventory_image = "shields_inv_shield_gold.png", + groups = {armor_shield=1, armor_heal=6, armor_use=300, + physics_speed=-0.04, physics_gravity=0.04}, + armor_groups = {fleshy=10}, + damage_groups = {cracky=1, snappy=2, choppy=2, crumbly=3, level=2}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_dig_metal") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_dug_metal") + end, + }) +end + +if armor.materials.mithril then + armor:register_armor("shields:shield_mithril", { + description = S("Mithril Shield"), + inventory_image = "shields_inv_shield_mithril.png", + groups = {armor_shield=1, armor_heal=12, armor_use=100}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_glass_footstep") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_break_glass") + end, + }) +end + +if armor.materials.crystal then + armor:register_armor("shields:shield_crystal", { + description = S("Crystal Shield"), + inventory_image = "shields_inv_shield_crystal.png", + groups = {armor_shield=1, armor_heal=12, armor_use=100, armor_fire=1}, + armor_groups = {fleshy=15}, + damage_groups = {cracky=2, snappy=1, level=3}, + reciprocate_damage = true, + on_damage = function(player, index, stack) + play_sound_effect(player, "default_glass_footstep") + end, + on_destroy = function(player, index, stack) + play_sound_effect(player, "default_break_glass") + end, + }) +end + +for k, v in pairs(armor.materials) do + minetest.register_craft({ + output = "shields:shield_"..k, + recipe = { + {v, v, v}, + {v, v, v}, + {"", v, ""}, + }, + }) +end diff --git a/mods/shields/textures/preview_index.txt b/mods/shields/textures/preview_index.txt new file mode 100644 index 0000000..4408c61 --- /dev/null +++ b/mods/shields/textures/preview_index.txt @@ -0,0 +1,11 @@ +shields/textures/shields_shield_wood.png:shield +shields/textures/shields_shield_enhanced_wood.png:shield +shields/textures/shields_shield_cactus.png:shield +shields/textures/shields_shield_enhanced_cactus.png:shield +shields/textures/shields_shield_steel.png:shield +shields/textures/shields_shield_bronze.png:shield +shields/textures/shields_shield_gold.png:shield +shields/textures/shields_shield_diamond.png:shield +shields/textures/shields_shield_mithril.png:shield +shields/textures/shields_shield_crystal.png:shield +shields/textures/shields_shield_admin.png:shield diff --git a/mods/shields/textures/shields_inv_shield_admin.png b/mods/shields/textures/shields_inv_shield_admin.png new file mode 100644 index 0000000..0b0637e Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_admin.png differ diff --git a/mods/shields/textures/shields_inv_shield_bronze.png b/mods/shields/textures/shields_inv_shield_bronze.png new file mode 100644 index 0000000..af47896 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_bronze.png differ diff --git a/mods/shields/textures/shields_inv_shield_cactus.png b/mods/shields/textures/shields_inv_shield_cactus.png new file mode 100644 index 0000000..d5c9ae4 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_cactus.png differ diff --git a/mods/shields/textures/shields_inv_shield_crystal.png b/mods/shields/textures/shields_inv_shield_crystal.png new file mode 100644 index 0000000..ebb73db Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_crystal.png differ diff --git a/mods/shields/textures/shields_inv_shield_diamond.png b/mods/shields/textures/shields_inv_shield_diamond.png new file mode 100644 index 0000000..0e79d97 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_diamond.png differ diff --git a/mods/shields/textures/shields_inv_shield_enhanced_cactus.png b/mods/shields/textures/shields_inv_shield_enhanced_cactus.png new file mode 100644 index 0000000..c5dc4d0 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_enhanced_cactus.png differ diff --git a/mods/shields/textures/shields_inv_shield_enhanced_wood.png b/mods/shields/textures/shields_inv_shield_enhanced_wood.png new file mode 100644 index 0000000..13baede Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_enhanced_wood.png differ diff --git a/mods/shields/textures/shields_inv_shield_gold.png b/mods/shields/textures/shields_inv_shield_gold.png new file mode 100644 index 0000000..d0bd027 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_gold.png differ diff --git a/mods/shields/textures/shields_inv_shield_mithril.png b/mods/shields/textures/shields_inv_shield_mithril.png new file mode 100644 index 0000000..a55fb00 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_mithril.png differ diff --git a/mods/shields/textures/shields_inv_shield_steel.png b/mods/shields/textures/shields_inv_shield_steel.png new file mode 100644 index 0000000..5417632 Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_steel.png differ diff --git a/mods/shields/textures/shields_inv_shield_wood.png b/mods/shields/textures/shields_inv_shield_wood.png new file mode 100644 index 0000000..407533f Binary files /dev/null and b/mods/shields/textures/shields_inv_shield_wood.png differ diff --git a/mods/shields/textures/shields_shield_admin.png b/mods/shields/textures/shields_shield_admin.png new file mode 100644 index 0000000..764c3bb Binary files /dev/null and b/mods/shields/textures/shields_shield_admin.png differ diff --git a/mods/shields/textures/shields_shield_admin_preview.png b/mods/shields/textures/shields_shield_admin_preview.png new file mode 100644 index 0000000..1d64766 Binary files /dev/null and b/mods/shields/textures/shields_shield_admin_preview.png differ diff --git a/mods/shields/textures/shields_shield_bronze.png b/mods/shields/textures/shields_shield_bronze.png new file mode 100644 index 0000000..d2a3561 Binary files /dev/null and b/mods/shields/textures/shields_shield_bronze.png differ diff --git a/mods/shields/textures/shields_shield_bronze_preview.png b/mods/shields/textures/shields_shield_bronze_preview.png new file mode 100644 index 0000000..3942471 Binary files /dev/null and b/mods/shields/textures/shields_shield_bronze_preview.png differ diff --git a/mods/shields/textures/shields_shield_cactus.png b/mods/shields/textures/shields_shield_cactus.png new file mode 100644 index 0000000..889ac94 Binary files /dev/null and b/mods/shields/textures/shields_shield_cactus.png differ diff --git a/mods/shields/textures/shields_shield_cactus_preview.png b/mods/shields/textures/shields_shield_cactus_preview.png new file mode 100644 index 0000000..1b46f1e Binary files /dev/null and b/mods/shields/textures/shields_shield_cactus_preview.png differ diff --git a/mods/shields/textures/shields_shield_crystal.png b/mods/shields/textures/shields_shield_crystal.png new file mode 100644 index 0000000..03882e8 Binary files /dev/null and b/mods/shields/textures/shields_shield_crystal.png differ diff --git a/mods/shields/textures/shields_shield_crystal_preview.png b/mods/shields/textures/shields_shield_crystal_preview.png new file mode 100644 index 0000000..8dc632e Binary files /dev/null and b/mods/shields/textures/shields_shield_crystal_preview.png differ diff --git a/mods/shields/textures/shields_shield_diamond.png b/mods/shields/textures/shields_shield_diamond.png new file mode 100644 index 0000000..d1641b7 Binary files /dev/null and b/mods/shields/textures/shields_shield_diamond.png differ diff --git a/mods/shields/textures/shields_shield_diamond_preview.png b/mods/shields/textures/shields_shield_diamond_preview.png new file mode 100644 index 0000000..87fd958 Binary files /dev/null and b/mods/shields/textures/shields_shield_diamond_preview.png differ diff --git a/mods/shields/textures/shields_shield_enhanced_cactus.png b/mods/shields/textures/shields_shield_enhanced_cactus.png new file mode 100644 index 0000000..13884ff Binary files /dev/null and b/mods/shields/textures/shields_shield_enhanced_cactus.png differ diff --git a/mods/shields/textures/shields_shield_enhanced_cactus_preview.png b/mods/shields/textures/shields_shield_enhanced_cactus_preview.png new file mode 100644 index 0000000..d8227a8 Binary files /dev/null and b/mods/shields/textures/shields_shield_enhanced_cactus_preview.png differ diff --git a/mods/shields/textures/shields_shield_enhanced_wood.png b/mods/shields/textures/shields_shield_enhanced_wood.png new file mode 100644 index 0000000..64f5331 Binary files /dev/null and b/mods/shields/textures/shields_shield_enhanced_wood.png differ diff --git a/mods/shields/textures/shields_shield_enhanced_wood_preview.png b/mods/shields/textures/shields_shield_enhanced_wood_preview.png new file mode 100644 index 0000000..97ca378 Binary files /dev/null and b/mods/shields/textures/shields_shield_enhanced_wood_preview.png differ diff --git a/mods/shields/textures/shields_shield_gold.png b/mods/shields/textures/shields_shield_gold.png new file mode 100644 index 0000000..e1aecfd Binary files /dev/null and b/mods/shields/textures/shields_shield_gold.png differ diff --git a/mods/shields/textures/shields_shield_gold_preview.png b/mods/shields/textures/shields_shield_gold_preview.png new file mode 100644 index 0000000..103e0bc Binary files /dev/null and b/mods/shields/textures/shields_shield_gold_preview.png differ diff --git a/mods/shields/textures/shields_shield_mithril.png b/mods/shields/textures/shields_shield_mithril.png new file mode 100644 index 0000000..2e14503 Binary files /dev/null and b/mods/shields/textures/shields_shield_mithril.png differ diff --git a/mods/shields/textures/shields_shield_mithril_preview.png b/mods/shields/textures/shields_shield_mithril_preview.png new file mode 100644 index 0000000..8adb978 Binary files /dev/null and b/mods/shields/textures/shields_shield_mithril_preview.png differ diff --git a/mods/shields/textures/shields_shield_steel.png b/mods/shields/textures/shields_shield_steel.png new file mode 100644 index 0000000..22ddb07 Binary files /dev/null and b/mods/shields/textures/shields_shield_steel.png differ diff --git a/mods/shields/textures/shields_shield_steel_preview.png b/mods/shields/textures/shields_shield_steel_preview.png new file mode 100644 index 0000000..96fbf9a Binary files /dev/null and b/mods/shields/textures/shields_shield_steel_preview.png differ diff --git a/mods/shields/textures/shields_shield_wood.png b/mods/shields/textures/shields_shield_wood.png new file mode 100644 index 0000000..129f9f0 Binary files /dev/null and b/mods/shields/textures/shields_shield_wood.png differ diff --git a/mods/shields/textures/shields_shield_wood_preview.png b/mods/shields/textures/shields_shield_wood_preview.png new file mode 100644 index 0000000..d167738 Binary files /dev/null and b/mods/shields/textures/shields_shield_wood_preview.png differ diff --git a/mods/shop/.gitignore b/mods/shop/.gitignore new file mode 100755 index 0000000..1377554 --- /dev/null +++ b/mods/shop/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/mods/shop/README.md b/mods/shop/README.md new file mode 100644 index 0000000..17f9aa0 --- /dev/null +++ b/mods/shop/README.md @@ -0,0 +1,2 @@ +# shop +License GPL3 diff --git a/mods/shop/depends.txt b/mods/shop/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/shop/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/shop/init.lua b/mods/shop/init.lua new file mode 100644 index 0000000..53fdb05 --- /dev/null +++ b/mods/shop/init.lua @@ -0,0 +1,310 @@ +-- `Shop' mod for Minetest/DCBL +-- Copyright 2017 James Stevenson +-- Licensed GNU General Public License 3 +-- (Or higher, as you please.) +-- minetest.net + +local output = function(name, message) + minetest.chat_send_player(name, message) +end + +local function get_shop_formspec(pos, p) + local meta = minetest.get_meta(pos) + local spos = pos.x.. "," ..pos.y .. "," .. pos.z + local formspec = + "size[8,7]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "label[0,1;Item]" .. + "label[3,1;Cost]" .. + "button[0,0;2,1;ok;Buy]" .. + "button_exit[3,0;2,1;exit;Exit]" .. + "button[6,0;2,1;stock;Stock]" .. + "button[6,1;2,1;register;Register]" .. + "button[0,2;1,1;prev;<]" .. + "button[1,2;1,1;next;>]" .. + "list[nodemeta:" .. spos .. ";sell" .. p .. ";1,1;1,1;]" .. + "list[nodemeta:" .. spos .. ";buy" .. p .. ";4,1;1,1;]" .. + "list[current_player;main;0,3.25;8,4;]" + return formspec +end + +local formspec_register = + "size[8,9]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "label[0,0;Register]" .. + "list[current_name;register;0,0.75;8,4;]" .. + "list[current_player;main;0,5.25;8,4;]" .. + "listring[]" + +local formspec_stock = + "size[8,9]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "label[0,0;Stock]" .. + "list[current_name;stock;0,0.75;8,4;]" .. + "list[current_player;main;0,5.25;8,4;]" .. + "listring[]" + +minetest.register_privilege("shop_admin", { + description = "Shop administration and maintainence", + give_to_singleplayer = false, + give_to_admin = true, +}) + +minetest.register_node("shop:shop", { + description = "Shop", + tiles = { + "shop_shop_topbottom.png", + "shop_shop_topbottom.png", + "shop_shop_side.png", + "shop_shop_side.png", + "shop_shop_side.png", + "shop_shop_front.png", + }, + groups = {choppy = 3, oddly_breakable_by_hand = 1}, + paramtype2 = "facedir", + after_place_node = function(pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + meta:set_string("pos", pos.x .. "," .. pos.y .. "," .. pos.z) + local owner = placer:get_player_name() + + meta:set_string("owner", owner) + meta:set_string("infotext", "Shop (Owned by " .. owner .. ")") + meta:set_string("formspec", get_shop_formspec(pos, 1)) + meta:set_string("admin_shop", "false") + meta:set_int("pages_current", 1) + meta:set_int("pages_total", 1) + + local inv = meta:get_inventory() + inv:set_size("buy1", 1) + inv:set_size("sell1", 1) + inv:set_size("stock", 8*4) + inv:set_size("register", 8*4) + end, + on_skeleton_key_use = function(pos, player) + if not minetest.check_player_privs(player, "shop_admin") then + return + end + local meta = minetest.get_meta(pos) + if meta:get_string("admin_shop") == "false" then + output(player:get_player_name(), "Enabling infinite stocks in shop.") + meta:set_string("admin_shop", "true") + elseif meta:get_string("admin_shop") == "true" then + output(player:get_player_name(), "Disabling infinite stocks in shop.") + meta:set_string("admin_shop", "false") + end + end, + on_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + local node_pos = minetest.string_to_pos(meta:get_string("pos")) + local owner = meta:get_string("owner") + local inv = meta:get_inventory() + local pg_current = meta:get_int("pages_current") + local pg_total = meta:get_int("pages_total") + local s = inv:get_list("sell" .. pg_current) + local b = inv:get_list("buy" .. pg_current) + local stk = inv:get_list("stock") + local reg = inv:get_list("register") + local player = sender:get_player_name() + local pinv = sender:get_inventory() + local admin_shop = meta:get_string("admin_shop") + + if fields.next then + if pg_total < 32 and + pg_current == pg_total and + player == owner and + not (inv:is_empty("sell" .. pg_current) or inv:is_empty("buy" .. pg_current)) then + inv:set_size("buy" .. pg_current + 1, 1) + inv:set_size("sell" .. pg_current + 1, 1) + meta:set_string("formspec", get_shop_formspec(node_pos, pg_current + 1)) + meta:set_int("pages_current", pg_current + 1) + meta:set_int("pages_total", pg_current + 1) + elseif pg_total > 1 then + if inv:is_empty("sell" .. pg_current) and inv:is_empty("buy" .. pg_current) then + if pg_current == pg_total then + meta:set_int("pages_total", pg_total - 1) + else + for i = pg_current, pg_total do + inv:set_list("buy" .. i, inv:get_list("buy" .. i + 1)) + inv:set_list("sell" .. i, inv:get_list("sell" .. i + 1)) + inv:set_list("buy" .. i + 1, nil) + inv:set_list("sell" .. i + 1, nil) + end + meta:set_int("pages_total", pg_total - 1) + pg_current = pg_current - 1 + end + end + if pg_current < pg_total then + meta:set_int("pages_current", pg_current + 1) + else + meta:set_int("pages_current", 1) + end + meta:set_string("formspec", get_shop_formspec(node_pos, meta:get_int("pages_current"))) + end + elseif fields.prev then + if pg_total > 1 then + if inv:is_empty("sell" .. pg_current) and inv:is_empty("buy" .. pg_current) then + if pg_current == pg_total then + meta:set_int("pages_total", pg_total - 1) + else + for i = pg_current, pg_total do + inv:set_list("buy" .. i, inv:get_list("buy" .. i + 1)) + inv:set_list("sell" .. i, inv:get_list("sell" .. i + 1)) + inv:set_list("buy" .. i + 1, nil) + inv:set_list("sell" .. i + 1, nil) + end + meta:set_int("pages_total", pg_total - 1) + pg_current = pg_current + 1 + end + end + if pg_current == 1 and pg_total > 1 then + meta:set_int("pages_current", pg_total) + elseif pg_current > 1 then + meta:set_int("pages_current", pg_current - 1) + end + meta:set_string("formspec", get_shop_formspec(node_pos, meta:get_int("pages_current"))) + end + elseif fields.register then + if player ~= owner and (not minetest.check_player_privs(player, "shop_admin")) then + output(player, "Only the shop owner can open the register.") + return + else + minetest.show_formspec(player, "shop:shop", formspec_register) + end + elseif fields.stock then + if player ~= owner and (not minetest.check_player_privs(player, "shop_admin")) then + output(player, "Only the shop owner can open the stock.") + return + else + minetest.show_formspec(player, "shop:shop", formspec_stock) + end + elseif fields.ok then + -- Shop's closed if not set up, or the till is full. + if inv:is_empty("sell" .. pg_current) or + inv:is_empty("buy" .. pg_current) or + (not inv:room_for_item("register", b[1])) then + output(player, "Shop closed.") + return + end + + -- Player has funds. + if pinv:contains_item("main", b[1]) then + -- Player has space for the goods. + if pinv:room_for_item("main", s[1]) then + -- There's inventory in stock. + if inv:contains_item("stock", s[1]) then + pinv:remove_item("main", b[1]) -- Take the funds. + inv:add_item("register", b[1]) -- Fill the till. + inv:remove_item("stock", s[1]) -- Take one from the stock. + pinv:add_item("main", s[1]) -- Give it to the player. + elseif admin_shop == "true" then + pinv:remove_item("main", b[1]) + inv:add_item("register", b[1]) + pinv:add_item("main", s[1]) + else + output(player, "Shop is out of inventory!") + end + else + output(player, "You're all filled up!") + end + else + output(player, "Not enough credits!") -- 32X. + end + end + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local inv = meta:get_inventory() + local pg_current = meta:get_string("pages_current") + local s = inv:get_list("sell" .. pg_current) + local n = stack:get_name() + local playername = player:get_player_name() + if playername ~= owner and + (not minetest.check_player_privs(playername, "shop_admin")) then + return 0 + else + return stack:get_count() + end + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local playername = player:get_player_name() + if playername ~= owner and + (not minetest.check_player_privs(playername, "shop_admin"))then + return 0 + else + return stack:get_count() + end + end, + allow_metadata_inventory_move = function(pos, _, _, _, _, count, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local playername = player:get_player_name() + if playername ~= owner and + (not minetest.check_player_privs(playername, "shop_admin")) then + return 0 + else + return count + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + local inv = meta:get_inventory() + return player:get_player_name() == owner and + inv:is_empty("register") and + inv:is_empty("stock") and + -- FIXME Make all contents in the buy/sell lists drop as items. + inv:is_empty("buy1") and + inv:is_empty("sell1") + end, + +}) + +minetest.register_craftitem("shop:coin", { + + description = "Gold Coin", + inventory_image = "shop_coin.png", +}) + +minetest.clear_craft({recipe={{"default:gold_ingot"}}}) +minetest.register_craft({ + output = "shop:coin 9", + recipe = { + {"default:gold_ingot"}, + } +}) +---[[ +minetest.register_craft({ + output = "default:skeleton_key", + type = "shapeless", + recipe = { + "default:gold_ingot", "default:gold_ingot", + } +}) +--]] + +minetest.register_craft({ + output = "default:gold_ingot", + recipe = { + {"shop:coin", "shop:coin", "shop:coin"}, + {"shop:coin", "shop:coin", "shop:coin"}, + {"shop:coin", "shop:coin", "shop:coin"} + } +}) + +minetest.register_craft({ + output = "shop:shop", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"group:wood", "default:gold_ingot", "group:wood"}, + {"group:wood", "group:wood", "group:wood"} + } +}) diff --git a/mods/shop/textures/shop_coin.png b/mods/shop/textures/shop_coin.png new file mode 100644 index 0000000..58f2500 Binary files /dev/null and b/mods/shop/textures/shop_coin.png differ diff --git a/mods/shop/textures/shop_shop_front.png b/mods/shop/textures/shop_shop_front.png new file mode 100644 index 0000000..48354a6 Binary files /dev/null and b/mods/shop/textures/shop_shop_front.png differ diff --git a/mods/shop/textures/shop_shop_side.png b/mods/shop/textures/shop_shop_side.png new file mode 100644 index 0000000..687fa30 Binary files /dev/null and b/mods/shop/textures/shop_shop_side.png differ diff --git a/mods/shop/textures/shop_shop_topbottom.png b/mods/shop/textures/shop_shop_topbottom.png new file mode 100644 index 0000000..fe9438a Binary files /dev/null and b/mods/shop/textures/shop_shop_topbottom.png differ diff --git a/mods/sneak_jump/LICENSE b/mods/sneak_jump/LICENSE new file mode 100644 index 0000000..e5ab03e --- /dev/null +++ b/mods/sneak_jump/LICENSE @@ -0,0 +1,502 @@ + 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/mods/sneak_jump/README b/mods/sneak_jump/README new file mode 100644 index 0000000..469f6e7 --- /dev/null +++ b/mods/sneak_jump/README @@ -0,0 +1,13 @@ +Minetest Sneak Jump Mod + +Allows to sneak jump while player is holding the Use key (default [E]) only. +Adds (optional) stamina. Stamina drain and fill rates are configurable, as well +as sprinting speed, jump height, and gravity. Check settingtypes.txt for the +configuration parameters, or look in the Advanced Settings tab in Minetest. + +When not sprinting, `new_move` is on and `sneak_glitch` is disabled. Sprinting +inverts these two physics overrides, allowing sneak jumping using the old move +code. + +License: LGPL 2.1+ +sneak_jump_eat.ogg is: hunger_eat.ogg - BlockMen (CC-BY 3.0) diff --git a/mods/sneak_jump/init.lua b/mods/sneak_jump/init.lua new file mode 100644 index 0000000..c7e7016 --- /dev/null +++ b/mods/sneak_jump/init.lua @@ -0,0 +1,536 @@ +-- Modified Physics (sneak_jump) +-- By James Stevenson (c) 2018 +-- GNU GPL v3 + +local regen_delay = 3 +local hunger_delay = 3.1 + +-- Make a sound on item pickup. +local old_on_step = minetest.registered_entities["__builtin:item"].on_step +minetest.registered_entities["__builtin:item"].on_step = function(self, dtime) + for _, o in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1)) do + local pq = o:is_player() and o:get_meta():get("class") ~= "node" + if pq then + local i = o:get_inventory() + if i and self.itemstring ~= "" and self.age > 1 then + local s = i:add_item("main", self.itemstring) + if s and not s:is_empty() then + self:set_item(s) + break + end + minetest.sound_play({name = "sneak_jump_item", gain = 0.033}, { + object = self.object, + max_hear_distance = 4, + pitch = 0.9, + }) + self.itemstring = "" + self.object:remove() + return + end + end + end + old_on_step(self, dtime) +end +minetest.registered_entities["__builtin:item"].on_punch = function(self, hitter) + if hitter:get_meta():get("class") == "node" then + return + end + local i = hitter:get_inventory() + if i and self.itemstring ~= "" then + local s = i:add_item("main", self.itemstring) + if s and not s:is_empty() then + self:set_item(s) + return + end + end + minetest.sound_play("sneak_jump_item", { + object = self.object, + max_hear_distance = 4, + gain = 0.033, + pitch = 0.9, + }) + self.itemstring = "" + self.object:remove() +end + +sneak_jump = {} +sneak_jump.sprinting = {} +sneak_jump.sneaking = {} +sneak_jump.meters = {} + +local pitch_table = { + [1] = 0.98, + [2] = 0.99, + [3] = 1, + [4] = 1.01, + [5] = 1.034, + [6] = 1.05, + [7] = 1.06, + [8] = 1.09, + [9] = 1.12, +} + +local settings = minetest.settings +local ceil = math.ceil +local floor = math.floor +local random = math.random +-- Whether player has stamina. +local stamina_drains = settings:get("sneak_jump.stamina_drains") or + settings:get("enable_damage") +stamina_drains = stamina_drains == "true" or nil +-- The rate of stamina drain while sprinting. +local drain_rate = settings:get("sneak_jump.drain_rate") or 0.075 +-- The rate of stamina fill while not sprinting. +local fill_rate = settings:get("sneak_jump.fill_rate") or 0.5 +-- Creative mode check. +local creative = settings:get("creative_mode") == "true" +-- Hunger +local hunger = settings:get("sneak_jump.hunger") or true +if hunger == "false" then + hunger = nil +end +local starve_rate = tonumber(settings:get("sneak_jump.starve_rate")) or 0.5 +local starve_timer = 0 +-- Regen +local regen_rate = tonumber(settings:get("sneak_jump.regen_rate")) or 1 +local regen_timer = 0 +-- Food governor +local eat_div = tonumber(settings:get("sneak_jump.food_governor")) or 0.5 + +-- Physics tables. +sneak_jump.default_physics = { + speed = 1, + jump = 1, + gravity = 1, + new_move = true, + sneak_glitch = false, +} +default_physics = sneak_jump.default_physics +sneak_jump.default_physics_scout = { + speed = 1.25, + jump = 1.25, + gravity = 0.95, + new_move = true, + sneak_glitch = true, +} +default_physics_scout = sneak_jump.default_physics_scout +local jump_setting = settings:get("sneak_jump.jump") or 1.25 +local modified_physics = { + speed = settings:get("sneak_jump.speed") or 1.5, + jump = jump_setting, + gravity = settings:get("gravity") or 0.95, + new_move = false, + sneak_glitch = true, +} +local modified_physics_scout = { + speed = 1.999, + jump = 1.5, + gravity = 0.89, + new_move = false, + sneak_glitch = true, +} +-- Functions +local function set_physics(player, physics_table) + player:set_physics_override(physics_table) +end + +local function eat_sound(pitch, player) + minetest.sound_play("sneak_jump_eat", { + object = player, + pitch = pitch, + }) +end + +-- Remove bubbles. +minetest.hud_replace_builtin("breath", { + hud_elem_type = "statbar", + text = "", +}) + +local function regen(player) + if not player then + return + end + if not player:get_properties() then + return minetest.after(regen_delay, regen, player) + end + local sat = player:get_meta():get_float("satiation") or 0 + local hp = player:get_hp() + local hp_max = player:get_properties().hp_max + if sat > 15 and hp ~= hp_max and hp ~= 0 then + player:set_hp(hp + 1) + end + return minetest.after(regen_delay, regen, player) +end + +local function starve(player, amount) + if not player then + return + end + local meta = player:get_meta() + local sat = meta:get_float("satiation") or 0 + sat = sat - amount + jas0.level(player, amount / 2) + if sat < 0 then + sat = 0 + end + meta:set_float("satiation", sat) + local name = player:get_player_name() + if sneak_jump.meters[name] and + sneak_jump.meters[name].satiation and + meta:get("class") ~= "node" then + player:hud_change(sneak_jump.meters[name].satiation, + "number", ceil(sat)) + end +end + +function sneak_jump.hud_update(player, repeater) + if not player then + return + end + local meta = player:get_meta() + local name = player:get_player_name() + local armor_wear_level = meta:get_int("3d_armor_wear") or 0 + if meta:get("class") == "node" then + armor_wear_level = 0 + end + if sneak_jump.meters[name] and sneak_jump.meters[name].armor then + player:hud_change(sneak_jump.meters[name].armor, + "number", ceil(armor_wear_level)) + end + if repeater then + return minetest.after(2, sneak_jump.hud_update, player, true) + end +end + +function sneak_jump.cdr(player, tbl) + if not player then + return + end + local control = player:get_player_control() + if tbl then + for i = 1, #tbl do + if control[tbl[i]] then + return true + end + end + else + return control.up or + control.down or + control.left or + control.right or + control.jumping + end +end + +local function hunger(player) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + if player:get_hp() == 0 or + player:get_meta():get("class") == "node" then + return minetest.after(hunger_delay, hunger, player) + end + if meta:get_float("satiation") < 1 then + player:set_hp(player:get_hp() - 1) + starve(player, 1) + elseif sneak_jump.cdr(player, {"LMB", "RMB"}) then + starve(player, 0.25) + elseif sneak_jump.cdr(player) then + starve(player, 0.1) + else + starve(player, 0.02) + end + return minetest.after(hunger_delay, hunger, player) +end + +local function physics(player) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + local name = player:get_player_name() + if not sneak_jump.meters[name] or + meta:get("class") == "node" then + return minetest.after(0.1, physics, player) + end + local scout = meta:get_string("class") == "scout" + local hp = player:get_hp() + if hp < 1 then + return minetest.after(0.1, physics, player) + end + local control = player:get_player_control() + local aux1 = control.aux1 + local sneaking = control.sneak + local jumping = control.jump + local sprinting = sneak_jump.sprinting[name] + local stamina = meta:get_float("stamina") + local sat = meta:get_float("satiation") + local cdr = control.up or + control.down or + control.left or + control.right or + jumping + if sat < 1 then + if stamina > 1 then + stamina = stamina - drain_rate + end + elseif aux1 and not sprinting and cdr then + if stamina_drains and stamina > 1 or + not stamina_drains then + if scout then + set_physics(player, modified_physics_scout) + else + set_physics(player, modified_physics) + end + sprinting = true + end + elseif sprinting and not aux1 or + sprinting and not cdr then + if scout then + set_physics(player, default_physics_scout) + else + set_physics(player, default_physics) + end + sprinting = false + end + if sprinting and stamina > 0 then + local new_sat = sat / 10 + if new_sat <= 0 then + new_sat = 0.1 + end + local new_drain_rate = drain_rate / new_sat + stamina = stamina - new_drain_rate + elseif sprinting and stamina < 1 then + if scout then + set_physics(player, default_physics_scout) + else + set_physics(player, default_physics) + end + elseif stamina < 20 and not sprinting then + if hunger and sat < 1 then + stamina = stamina - drain_rate + else + local new_fill_rate = fill_rate + if cdr then + new_fill_rate = fill_rate * 0.1 + end + stamina = stamina + new_fill_rate + end + end + meta:set_float("stamina", stamina) + player:hud_change(sneak_jump.meters[name].stamina, + "number", stamina) + if sneaking and not sneak_jump.sneaking[name] then + player:set_properties{makes_footstep_sound = false} + elseif sneak_jump.sneaking[name] and not sneaking then + if not scout then + player:set_properties{makes_footstep_sound = true} + end + end + sneak_jump.sprinting[name] = sprinting + sneak_jump.sneaking[name] = sneaking + return minetest.after(0.1, physics, player) +end + +minetest.register_on_newplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + --meta:set_float("stamina", 20) + meta:set_float("satiation", 20) +end) + +minetest.register_on_joinplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + if not meta then + return + end + local scout = meta:get_string("class") == "scout" + if scout then + set_physics(player, default_physics_scout) + else + set_physics(player, default_physics) + end + local name = player:get_player_name() + sneak_jump.sneaking[name] = false + sneak_jump.meters[name] = {} + + -- Add armor HUD statbar. + local armor_wear = meta:get_int("3d_armor_wear") or 0 + local class = meta:get("class") + sneak_jump.meters[name]["armor"] = player:hud_add({ + hud_elem_type = "statbar", + position = {x = 0.5, y = 1}, + text = "sneak_jump_armor_sb.png", + number = armor_wear, + direction = 0, + size = {x = 24, y = 21}, + offset = {x = 25, y = -(48 + 46 + 16)}, + }) + + -- Add stamina HUD statbar. + meta:set_float("stamina", 20) + local stam = 20 + if player:get_hp() == 0 or + class == "node" then + stam = 0 + end + sneak_jump.meters[name]["stamina"] = player:hud_add({ + hud_elem_type = "statbar", + position = {x = 0.5, y = 1}, + text = "sneak_jump_stamina_sb.png", + number = stam, + direction = 0, + size = {x = 24, y = 24}, + offset = {x = 25, y = -(48 + 24 + 16)}, + }) + local sat = meta:get_float("satiation") + if class == "node" then + sat = 0 + end + --[[ + if not sat then + meta:set_float("satiation", 20) + sat = 20 + end + --]] + local offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 40)} + if settings:get("enable_damage") == "false" then + offset.y = -(48 + 24 + 16) + end + sneak_jump.meters[name]["satiation"] = player:hud_add({ + hud_elem_type = "statbar", + position = {x = 0.5, y = 1}, + text = "sneak_jump_satiation_sb.png", + number = sat, + direction = 0, + size = {x = 24, y = 24}, + offset = offset, + }) + minetest.after(0.1, hunger, player) + minetest.after(0.2, regen, player) + minetest.after(0.3, physics, player) + --minetest.after(0.4, sneak_jump.hud_update, player, true) +end) + +minetest.register_on_dieplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + local name = player:get_player_name() + meta:set_float("satiation", 0) + player:hud_change(sneak_jump.meters[name].satiation, + "number", 0) + meta:set_float("stamina", 0) + player:hud_change(sneak_jump.meters[name].stamina, + "number", 0) +end) + +minetest.register_on_respawnplayer(function(player) + if not player then + return + end + local meta = player:get_meta() + meta:set_float("satiation", 20) + meta:set_float("stamina", 20) + if meta:get("class") == "node" then + return + end + local name = player:get_player_name() + player:hud_change(sneak_jump.meters[name].satiation, + "number", 20) + player:hud_change(sneak_jump.meters[name].stamina, + "number", 20) +end) + +minetest.register_on_leaveplayer(function(player) + if not player then + return + end + local name = player:get_player_name() + sneak_jump.sprinting[name] = nil + sneak_jump.sneaking[name] = nil + sneak_jump.meters[name] = nil +end) + +minetest.register_on_item_eat(function(hp_change, + replace_with_item, itemstack, user, pointed_thing) + if not user then + return + end + local meta = user:get_meta() + if not meta then + return + end + local sat = meta:get_float("satiation") + local hp = user:get_hp() + if hp_change < 0 then + user:set_hp(hp + hp_change * 1.5) + if hp + hp_change < 1 then + eat_sound(pitch_table[random(#pitch_table)], user) + return "" + end + end + if hp_change > 0 and ceil(sat) >= 20 then + return itemstack + end + if hp + hp_change > 1 then + if hp_change > 1 then + hp_change = ceil(hp_change / eat_div) + end + sat = sat + hp_change + if sat > 20 then + sat = 20 + end + meta:set_float("satiation", sat) + local name = user:get_player_name() + user:hud_change(sneak_jump.meters[name].satiation, + "number", ceil(sat)) + end + itemstack:take_item() + eat_sound(pitch_table[random(#pitch_table)], user) + return itemstack +end) + +minetest.register_craftitem("sneak_jump:bandage", { + description = "Bandage", + inventory_image = "sneak_jump_bandage.png", + on_use = function(itemstack, user, pointed_thing) + local hp = user:get_hp() + local hp_max = user:get_properties().hp_max + if hp < hp_max then + user:set_hp(hp + 2) + if not creative then + itemstack:take_item() + end + end + return itemstack + end +}) + +minetest.register_craft({ + output = "sneak_jump:bandage", + recipe = { + {"farming:string", "farming:cotton", "farming:string"} + } +}) + +minetest.register_craft({ + output = "sneak_jump:bandage", + recipe = { + {"farming:string", "default:paper", "farming:string"} + } +}) diff --git a/mods/sneak_jump/mod.conf b/mods/sneak_jump/mod.conf new file mode 100644 index 0000000..0ddf107 --- /dev/null +++ b/mods/sneak_jump/mod.conf @@ -0,0 +1 @@ +name = sneak_jump diff --git a/mods/sneak_jump/settingtypes.txt b/mods/sneak_jump/settingtypes.txt new file mode 100644 index 0000000..18b742f --- /dev/null +++ b/mods/sneak_jump/settingtypes.txt @@ -0,0 +1,29 @@ +# Whether the player has stamina. +sneak_jump.stamina_drains (Stamina drains) bool true + +# Stamina drain rate. +sneak_jump.drain_rate (Stamina drain rate) float 0.1 + +# Stamina fill rate. +sneak_jump.fill_rate (Stamina fill rate) float 0.25 + +# Sneak jump sprint speed. +sneak_jump.speed (Sneak jump sprint speed) float 1.5 + +# Sneak jump height. +sneak_jump.jump (Sneak jump height) float 1.25 + +# Sneak jump gravity. +sneak_jump.gravity (Sneak jump gravity) float 0.95 + +# Whether player has hunger. +sneak_jump.hunger (Hunger) bool true + +# Hunger starvation rate. Lower equals faster starvation. +sneak_jump.starve_rate (Starve rate) float 0.5 + +# Heart regeneration rate. +sneak_jump.regen_rate (Regen rate) float 15.0 + +# How much to divide item eat points by. +sneak_jump.food_governor (Item eat amount limiter) float 2.0 diff --git a/mods/sneak_jump/sounds/sneak_jump_eat.ogg b/mods/sneak_jump/sounds/sneak_jump_eat.ogg new file mode 100644 index 0000000..9555204 Binary files /dev/null and b/mods/sneak_jump/sounds/sneak_jump_eat.ogg differ diff --git a/mods/sneak_jump/sounds/sneak_jump_item.1.ogg b/mods/sneak_jump/sounds/sneak_jump_item.1.ogg new file mode 100644 index 0000000..a25a7fe Binary files /dev/null and b/mods/sneak_jump/sounds/sneak_jump_item.1.ogg differ diff --git a/mods/sneak_jump/sounds/sneak_jump_item.2.ogg b/mods/sneak_jump/sounds/sneak_jump_item.2.ogg new file mode 100644 index 0000000..3a18055 Binary files /dev/null and b/mods/sneak_jump/sounds/sneak_jump_item.2.ogg differ diff --git a/mods/sneak_jump/sounds/sneak_jump_item.3.ogg b/mods/sneak_jump/sounds/sneak_jump_item.3.ogg new file mode 100644 index 0000000..e055703 Binary files /dev/null and b/mods/sneak_jump/sounds/sneak_jump_item.3.ogg differ diff --git a/mods/sneak_jump/sounds/sneak_jump_item.4.ogg b/mods/sneak_jump/sounds/sneak_jump_item.4.ogg new file mode 100644 index 0000000..025b11c Binary files /dev/null and b/mods/sneak_jump/sounds/sneak_jump_item.4.ogg differ diff --git a/mods/sneak_jump/textures/sneak_jump_armor_sb.png b/mods/sneak_jump/textures/sneak_jump_armor_sb.png new file mode 100644 index 0000000..136af70 Binary files /dev/null and b/mods/sneak_jump/textures/sneak_jump_armor_sb.png differ diff --git a/mods/sneak_jump/textures/sneak_jump_armor_sb_bg.png b/mods/sneak_jump/textures/sneak_jump_armor_sb_bg.png new file mode 100644 index 0000000..3240100 Binary files /dev/null and b/mods/sneak_jump/textures/sneak_jump_armor_sb_bg.png differ diff --git a/mods/sneak_jump/textures/sneak_jump_bandage.png b/mods/sneak_jump/textures/sneak_jump_bandage.png new file mode 100644 index 0000000..96c4e05 Binary files /dev/null and b/mods/sneak_jump/textures/sneak_jump_bandage.png differ diff --git a/mods/sneak_jump/textures/sneak_jump_satiation_sb.png b/mods/sneak_jump/textures/sneak_jump_satiation_sb.png new file mode 100644 index 0000000..a5cc2a1 Binary files /dev/null and b/mods/sneak_jump/textures/sneak_jump_satiation_sb.png differ diff --git a/mods/sneak_jump/textures/sneak_jump_stamina_sb.png b/mods/sneak_jump/textures/sneak_jump_stamina_sb.png new file mode 100644 index 0000000..eb661eb Binary files /dev/null and b/mods/sneak_jump/textures/sneak_jump_stamina_sb.png differ diff --git a/mods/spawn/README.txt b/mods/spawn/README.txt new file mode 100644 index 0000000..fc16c2a --- /dev/null +++ b/mods/spawn/README.txt @@ -0,0 +1,7 @@ +Minetest Game mod: spawn +======================== +See license.txt for license information. + +Authors of source code +---------------------- +paramat (MIT) diff --git a/mods/spawn/depends.txt b/mods/spawn/depends.txt new file mode 100644 index 0000000..548489e --- /dev/null +++ b/mods/spawn/depends.txt @@ -0,0 +1,2 @@ +default +beds? diff --git a/mods/spawn/init.lua b/mods/spawn/init.lua new file mode 100644 index 0000000..0eb126f --- /dev/null +++ b/mods/spawn/init.lua @@ -0,0 +1,154 @@ +spawn = {} + +-- Disable by mapgen, setting or if 'static_spawnpoint' is set +-------------------------------------------------------------- + +local mg_name = minetest.get_mapgen_setting("mg_name") +if mg_name == "v6" or mg_name == "singlenode" or + minetest.settings:get("static_spawnpoint") or + minetest.settings:get_bool("engine_spawn") then + return +end + + +-- Parameters +------------- + +-- Resolution of search grid in nodes. +local res = 64 +-- Number of points checked in the square search grid (edge * edge). +local checks = 128 * 128 +-- Starting point for biome checks. This also sets the y co-ordinate for all +-- points checked, so the suitable biomes must be active at this y. +local pos = {x = 0, y = 8, z = 0} + + +-- Table of suitable biomes + +local biome_ids = { + minetest.get_biome_id("taiga"), + minetest.get_biome_id("coniferous_forest"), + minetest.get_biome_id("deciduous_forest"), + minetest.get_biome_id("grassland"), + minetest.get_biome_id("savanna"), +} + +-- End of parameters +-------------------- + + +-- Direction table + +local dirs = { + {x = 0, y = 0, z = 1}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 0, z = -1}, + {x = 1, y = 0, z = 0}, +} + + +-- Initial variables + +local edge_len = 1 +local edge_dist = 0 +local dir_step = 0 +local dir_ind = 1 +local searched = false +local success = false +local spawn_pos = {} + + +--Functions +----------- + +-- Get next position on square search spiral + +local function next_pos() + if edge_dist == edge_len then + edge_dist = 0 + dir_ind = dir_ind + 1 + if dir_ind == 5 then + dir_ind = 1 + end + dir_step = dir_step + 1 + edge_len = math.floor(dir_step / 2) + 1 + end + + local dir = dirs[dir_ind] + local move = vector.multiply(dir, res) + + edge_dist = edge_dist + 1 + + return vector.add(pos, move) +end + + +-- Spawn position search + +local function search() + for iter = 1, checks do + local biome_data = minetest.get_biome_data(pos) + -- Sometimes biome_data is nil + local biome = biome_data and biome_data.biome + for id_ind = 1, #biome_ids do + local biome_id = biome_ids[id_ind] + if biome == biome_id then + local spawn_y = minetest.get_spawn_level(pos.x, pos.z) + if spawn_y then + spawn_pos = {x = pos.x, y = spawn_y, z = pos.z} + return true + end + end + end + + pos = next_pos() + end + + return false +end + + +-- On new player spawn and player respawn + +-- Search for spawn position once per server session. If successful, store +-- position and reposition players, otherwise leave them at engine spawn +-- position. + +spawn.on_spawn = function(player) + if not searched then + success = search() + searched = true + end + if success then + player:set_pos(spawn_pos) + end +end +minetest.register_chatcommand("spawn", { + description = "Return to static server spawn position!", + privs = "interact", + params = "", + func = function(name, param) + spawn.on_spawn(minetest.get_player_by_name(name)) + return true, "You are here." + end, +}) +minetest.register_on_newplayer(function(player) + spawn.on_spawn(player) +end) + +local enable_bed_respawn = minetest.settings:get_bool("enable_bed_respawn") +if enable_bed_respawn == nil then + enable_bed_respawn = true +end + +minetest.register_on_respawnplayer(function(player) + -- Avoid respawn conflict with beds mod + if beds and enable_bed_respawn and + beds.spawn[player:get_player_name()] then + return + end + + spawn.on_spawn(player) + + return true +end) diff --git a/mods/spawn/license.txt b/mods/spawn/license.txt new file mode 100644 index 0000000..a466aab --- /dev/null +++ b/mods/spawn/license.txt @@ -0,0 +1,24 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2018 paramat + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT diff --git a/mods/stairs/README.txt b/mods/stairs/README.txt new file mode 100644 index 0000000..26317f7 --- /dev/null +++ b/mods/stairs/README.txt @@ -0,0 +1,27 @@ +Minetest Game mod: stairs +========================= +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Kahrl (LGPLv2.1+) and +celeron55, Perttu Ahola (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures) +--------------------------- + +Textures +-------- +Copyright (c) 2018 Shara RedCat (CC BY-SA 3.0): + Derived from a texture by PilzAdam (CC BY-SA 3.0): + stairs_obsidian_glass_outer_stairside.png + stairs_obsidian_glass_stairside.png + +Copyright (c) 2018 TumeniNodes (CC BY-SA 3.0): + Derived from a texture by celeron55 (CC BY-SA 3.0) and + converted to bright white by Krock (CC BY-SA 3.0): + stairs_glass_stairside.png + stairs_glass_split.png + Derived from a texture by PilzAdam (CC BY-SA 3.0): + stairs_obsidian_glass_split.png diff --git a/mods/stairs/depends.txt b/mods/stairs/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/stairs/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/stairs/init.lua b/mods/stairs/init.lua new file mode 100644 index 0000000..e2ae0f5 --- /dev/null +++ b/mods/stairs/init.lua @@ -0,0 +1,927 @@ +-- Minetest 0.4 mod: stairs +-- See README.txt for licensing and other information. + + +-- Global namespace for functions + +stairs = {} + + +-- Register aliases for new pine node names + +minetest.register_alias("stairs:stair_pinewood", "stairs:stair_pine_wood") +minetest.register_alias("stairs:slab_pinewood", "stairs:slab_pine_wood") + + +-- Get setting for 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 + + if placer then + local placer_pos = placer:get_pos() + 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 + end + return minetest.item_place(itemstack, placer, pointed_thing, param2) +end + + +-- Register stair +-- Node will be called stairs:stair_ + +function stairs.register_stair(subname, recipeitem, groups, images, description, + sounds, worldaligntex) + -- Set backface culling and world-aligned textures + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + if worldaligntex then + stair_images[i].align_style = "world" + end + else + stair_images[i] = table.copy(image) + if stair_images[i].backface_culling == nil then + stair_images[i].backface_culling = true + end + if worldaligntex and stair_images[i].align_style == nil then + stair_images[i].align_style = "world" + end + end + end + local new_groups = table.copy(groups) + new_groups.stair = 1 + minetest.register_node(":stairs:stair_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = stair_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = new_groups, + sounds = sounds, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, + {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5}, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + return rotate_and_place(itemstack, placer, pointed_thing) + end, + }) + + -- for replace ABM + if replace then + minetest.register_node(":stairs:stair_" .. subname .. "upside_down", { + replace_name = "stairs:stair_" .. subname, + groups = {slabs_replace = 1}, + }) + end + + if recipeitem then + -- Recipe matches appearence in inventory + minetest.register_craft({ + output = 'stairs:stair_' .. subname .. ' 8', + recipe = { + {"", "", recipeitem}, + {"", recipeitem, recipeitem}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Use stairs to craft full blocks again (1:1) + minetest.register_craft({ + output = recipeitem .. ' 3', + recipe = { + {'stairs:stair_' .. subname, 'stairs:stair_' .. subname}, + {'stairs:stair_' .. subname, 'stairs:stair_' .. subname}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:stair_' .. subname, + burntime = math.floor(baseburntime * 0.75), + }) + end + end +end + + +-- Register slab +-- Node will be called stairs:slab_ + +function stairs.register_slab(subname, recipeitem, groups, images, description, + sounds, worldaligntex) + -- Set world-aligned textures + local slab_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + slab_images[i] = { + name = image, + } + if worldaligntex then + slab_images[i].align_style = "world" + end + else + slab_images[i] = table.copy(image) + if worldaligntex and image.align_style == nil then + slab_images[i].align_style = "world" + end + end + end + local new_groups = table.copy(groups) + new_groups.slab = 1 + minetest.register_node(":stairs:slab_" .. subname, { + description = description, + drawtype = "nodebox", + tiles = slab_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = new_groups, + sounds = sounds, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5}, + }, + on_place = function(itemstack, placer, pointed_thing) + local under = minetest.get_node(pointed_thing.under) + local wield_item = itemstack:get_name() + local player_name = placer and placer:get_player_name() or "" + local creative_enabled = (creative and creative.is_enabled_for + and creative.is_enabled_for(player_name)) + + 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) + + local p2 = under.param2 + + -- Placing a slab on an upside down slab should make it right-side up. + if p2 >= 20 and dir == 8 then + p2 = p2 - 20 + -- same for the opposite case: slab below normal slab + elseif p2 <= 3 and dir == 4 then + p2 = p2 + 20 + end + + -- else attempt to place node with proper param2 + minetest.item_place_node(ItemStack(wield_item), placer, pointed_thing, p2) + if not creative_enabled then + itemstack:take_item() + end + return itemstack + else + return rotate_and_place(itemstack, placer, pointed_thing) + end + end, + }) + + -- for replace ABM + if replace then + minetest.register_node(":stairs:slab_" .. subname .. "upside_down", { + replace_name = "stairs:slab_".. subname, + groups = {slabs_replace = 1}, + }) + end + + if recipeitem then + minetest.register_craft({ + output = 'stairs:slab_' .. subname .. ' 6', + recipe = { + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Use 2 slabs to craft a full block again (1:1) + minetest.register_craft({ + output = recipeitem, + recipe = { + {'stairs:slab_' .. subname}, + {'stairs:slab_' .. subname}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:slab_' .. subname, + burntime = math.floor(baseburntime * 0.5), + }) + end + end +end + + +-- Optionally replace old "upside_down" nodes with new param2 versions. +-- Disabled by default. + +if replace then + minetest.register_abm({ + label = "Slab replace", + nodenames = {"group:slabs_replace"}, + interval = 16, + chance = 1, + action = function(pos, node) + node.name = minetest.registered_nodes[node.name].replace_name + node.param2 = node.param2 + 20 + if node.param2 == 21 then + node.param2 = 23 + elseif node.param2 == 23 then + node.param2 = 21 + end + minetest.set_node(pos, node) + end, + }) +end + + +-- Register inner stair +-- Node will be called stairs:stair_inner_ + +function stairs.register_stair_inner(subname, recipeitem, groups, images, + description, sounds, worldaligntex) + -- Set backface culling and world-aligned textures + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + if worldaligntex then + stair_images[i].align_style = "world" + end + else + stair_images[i] = table.copy(image) + if stair_images[i].backface_culling == nil then + stair_images[i].backface_culling = true + end + if worldaligntex and stair_images[i].align_style == nil then + stair_images[i].align_style = "world" + end + end + end + local new_groups = table.copy(groups) + new_groups.stair = 1 + minetest.register_node(":stairs:stair_inner_" .. subname, { + description = "Inner " .. description, + drawtype = "nodebox", + tiles = stair_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = new_groups, + sounds = sounds, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, + {-0.5, 0.0, 0.0, 0.5, 0.5, 0.5}, + {-0.5, 0.0, -0.5, 0.0, 0.5, 0.0}, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + return rotate_and_place(itemstack, placer, pointed_thing) + end, + }) + + if recipeitem then + minetest.register_craft({ + output = 'stairs:stair_inner_' .. subname .. ' 7', + recipe = { + { "", recipeitem, ""}, + { recipeitem, "", recipeitem}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:stair_inner_' .. subname, + burntime = math.floor(baseburntime * 0.875), + }) + end + end +end + + +-- Register outer stair +-- Node will be called stairs:stair_outer_ + +function stairs.register_stair_outer(subname, recipeitem, groups, images, + description, sounds, worldaligntex) + -- Set backface culling and world-aligned textures + local stair_images = {} + for i, image in ipairs(images) do + if type(image) == "string" then + stair_images[i] = { + name = image, + backface_culling = true, + } + if worldaligntex then + stair_images[i].align_style = "world" + end + else + stair_images[i] = table.copy(image) + if stair_images[i].backface_culling == nil then + stair_images[i].backface_culling = true + end + if worldaligntex and stair_images[i].align_style == nil then + stair_images[i].align_style = "world" + end + end + end + local new_groups = table.copy(groups) + new_groups.stair = 1 + minetest.register_node(":stairs:stair_outer_" .. subname, { + description = "Outer " .. description, + drawtype = "nodebox", + tiles = stair_images, + paramtype = "light", + paramtype2 = "facedir", + is_ground_content = false, + groups = new_groups, + sounds = sounds, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.0, 0.5}, + {-0.5, 0.0, 0.0, 0.0, 0.5, 0.5}, + }, + }, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type ~= "node" then + return itemstack + end + + return rotate_and_place(itemstack, placer, pointed_thing) + end, + }) + + if recipeitem then + minetest.register_craft({ + output = 'stairs:stair_outer_' .. subname .. ' 6', + recipe = { + { "", "", ""}, + { "", recipeitem, ""}, + {recipeitem, recipeitem, recipeitem}, + }, + }) + + -- Fuel + local baseburntime = minetest.get_craft_result({ + method = "fuel", + width = 1, + items = {recipeitem} + }).time + if baseburntime > 0 then + minetest.register_craft({ + type = "fuel", + recipe = 'stairs:stair_outer_' .. subname, + burntime = math.floor(baseburntime * 0.625), + }) + end + end +end + + +-- Stair/slab registration function. +-- Nodes will be called stairs:{stair,slab}_ + +function stairs.register_stair_and_slab(subname, recipeitem, groups, images, + desc_stair, desc_slab, sounds, worldaligntex) + stairs.register_stair(subname, recipeitem, groups, images, desc_stair, + sounds, worldaligntex) + stairs.register_stair_inner(subname, recipeitem, groups, images, desc_stair, + sounds, worldaligntex) + stairs.register_stair_outer(subname, recipeitem, groups, images, desc_stair, + sounds, worldaligntex) + stairs.register_slab(subname, recipeitem, groups, images, desc_slab, + sounds, worldaligntex) +end + + +-- Register default stairs and slabs + +stairs.register_stair_and_slab( + "wood", + "default:wood", + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + {"default_wood.png"}, + "Wooden Stair", + "Wooden Slab", + default.node_sound_wood_defaults(), + false +) + +stairs.register_stair_and_slab( + "junglewood", + "default:junglewood", + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + {"default_junglewood.png"}, + "Jungle Wood Stair", + "Jungle Wood Slab", + default.node_sound_wood_defaults(), + false +) + +stairs.register_stair_and_slab( + "pine_wood", + "default:pine_wood", + {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + {"default_pine_wood.png"}, + "Pine Wood Stair", + "Pine Wood Slab", + default.node_sound_wood_defaults(), + false +) + +stairs.register_stair_and_slab( + "acacia_wood", + "default:acacia_wood", + {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, + {"default_acacia_wood.png"}, + "Acacia Wood Stair", + "Acacia Wood Slab", + default.node_sound_wood_defaults(), + false +) + +stairs.register_stair_and_slab( + "aspen_wood", + "default:aspen_wood", + {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + {"default_aspen_wood.png"}, + "Aspen Wood Stair", + "Aspen Wood Slab", + default.node_sound_wood_defaults(), + false +) + +stairs.register_stair_and_slab( + "stone", + "default:stone", + {cracky = 3}, + {"default_stone.png"}, + "Stone Stair", + "Stone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "cobble", + "default:cobble", + {cracky = 3}, + {"default_cobble.png"}, + "Cobblestone Stair", + "Cobblestone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "mossycobble", + "default:mossycobble", + {cracky = 3}, + {"default_mossycobble.png"}, + "Mossy Cobblestone Stair", + "Mossy Cobblestone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "stonebrick", + "default:stonebrick", + {cracky = 2}, + {"default_stone_brick.png"}, + "Stone Brick Stair", + "Stone Brick Slab", + default.node_sound_stone_defaults(), + false +) + +stairs.register_stair_and_slab( + "stone_block", + "default:stone_block", + {cracky = 2}, + {"default_stone_block.png"}, + "Stone Block Stair", + "Stone Block Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "desert_stone", + "default:desert_stone", + {cracky = 3}, + {"default_desert_stone.png"}, + "Desert Stone Stair", + "Desert Stone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "desert_cobble", + "default:desert_cobble", + {cracky = 3}, + {"default_desert_cobble.png"}, + "Desert Cobblestone Stair", + "Desert Cobblestone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "desert_stonebrick", + "default:desert_stonebrick", + {cracky = 2}, + {"default_desert_stone_brick.png"}, + "Desert Stone Brick Stair", + "Desert Stone Brick Slab", + default.node_sound_stone_defaults(), + false +) + +stairs.register_stair_and_slab( + "desert_stone_block", + "default:desert_stone_block", + {cracky = 2}, + {"default_desert_stone_block.png"}, + "Desert Stone Block Stair", + "Desert Stone Block Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "sandstone", + "default:sandstone", + {crumbly = 1, cracky = 3}, + {"default_sandstone.png"}, + "Sandstone Stair", + "Sandstone Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "sandstonebrick", + "default:sandstonebrick", + {cracky = 2}, + {"default_sandstone_brick.png"}, + "Sandstone Brick Stair", + "Sandstone Brick Slab", + default.node_sound_stone_defaults(), + false +) + +stairs.register_stair_and_slab( + "sandstone_block", + "default:sandstone_block", + {cracky = 2}, + {"default_sandstone_block.png"}, + "Sandstone Block Stair", + "Sandstone Block Slab", + default.node_sound_stone_defaults(), + true +) + +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(), + true +) + +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(), + false +) + +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(), + true +) + +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(), + true +) + +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(), + false +) + +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(), + true +) + +stairs.register_stair_and_slab( + "obsidian", + "default:obsidian", + {cracky = 1, level = 2}, + {"default_obsidian.png"}, + "Obsidian Stair", + "Obsidian Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "obsidianbrick", + "default:obsidianbrick", + {cracky = 1, level = 2}, + {"default_obsidian_brick.png"}, + "Obsidian Brick Stair", + "Obsidian Brick Slab", + default.node_sound_stone_defaults(), + false +) + +stairs.register_stair_and_slab( + "obsidian_block", + "default:obsidian_block", + {cracky = 1, level = 2}, + {"default_obsidian_block.png"}, + "Obsidian Block Stair", + "Obsidian Block Slab", + default.node_sound_stone_defaults(), + true +) + +stairs.register_stair_and_slab( + "brick", + "default:brick", + {cracky = 3}, + {"default_brick.png"}, + "Brick Stair", + "Brick Slab", + default.node_sound_stone_defaults(), + false +) + +stairs.register_stair_and_slab( + "steelblock", + "default:steelblock", + {cracky = 1, level = 2}, + {"default_steel_block.png"}, + "Steel Block Stair", + "Steel Block Slab", + default.node_sound_metal_defaults(), + true +) + +stairs.register_stair_and_slab( + "tinblock", + "default:tinblock", + {cracky = 1, level = 2}, + {"default_tin_block.png"}, + "Tin Block Stair", + "Tin Block Slab", + default.node_sound_metal_defaults(), + true +) + +stairs.register_stair_and_slab( + "copperblock", + "default:copperblock", + {cracky = 1, level = 2}, + {"default_copper_block.png"}, + "Copper Block Stair", + "Copper Block Slab", + default.node_sound_metal_defaults(), + true +) + +stairs.register_stair_and_slab( + "bronzeblock", + "default:bronzeblock", + {cracky = 1, level = 2}, + {"default_bronze_block.png"}, + "Bronze Block Stair", + "Bronze Block Slab", + default.node_sound_metal_defaults(), + true +) + +stairs.register_stair_and_slab( + "goldblock", + "default:goldblock", + {cracky = 1}, + {"default_gold_block.png"}, + "Gold Block Stair", + "Gold Block Slab", + default.node_sound_metal_defaults(), + true +) + +stairs.register_stair_and_slab( + "ice", + "default:ice", + {cracky = 3, puts_out_fire = 1, cools_lava = 1, slippery = 3}, + {"default_ice.png"}, + "Ice Stair", + "Ice Slab", + default.node_sound_glass_defaults(), + true +) + +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_snow_defaults(), + true +) + +-- Glass stair nodes need to be registered individually to utilize specialized textures. + +stairs.register_stair( + "glass", + "default:glass", + {cracky = 3}, + {"stairs_glass_split.png", "default_glass.png", + "stairs_glass_stairside.png^[transformFX", "stairs_glass_stairside.png", + "default_glass.png", "stairs_glass_split.png"}, + "Glass Stair", + default.node_sound_glass_defaults(), + false +) + +stairs.register_slab( + "glass", + "default:glass", + {cracky = 3}, + {"default_glass.png", "default_glass.png", "stairs_glass_split.png"}, + "Glass Slab", + default.node_sound_glass_defaults(), + false +) + +stairs.register_stair_inner( + "glass", + "default:glass", + {cracky = 3}, + {"stairs_glass_stairside.png^[transformR270", "default_glass.png", + "stairs_glass_stairside.png^[transformFX", "default_glass.png", + "default_glass.png", "stairs_glass_stairside.png"}, + "Glass Stair", + default.node_sound_glass_defaults(), + false +) + +stairs.register_stair_outer( + "glass", + "default:glass", + {cracky = 3}, + {"stairs_glass_stairside.png^[transformR90", "default_glass.png", + "stairs_glass_outer_stairside.png", "stairs_glass_stairside.png", + "stairs_glass_stairside.png^[transformR90","stairs_glass_outer_stairside.png"}, + "Glass Stair", + default.node_sound_glass_defaults(), + false +) + +stairs.register_stair( + "obsidian_glass", + "default:obsidian_glass", + {cracky = 3}, + {"stairs_obsidian_glass_split.png", "default_obsidian_glass.png", + "stairs_obsidian_glass_stairside.png^[transformFX", "stairs_obsidian_glass_stairside.png", + "default_obsidian_glass.png", "stairs_obsidian_glass_split.png"}, + "Obsidian Glass Stair", + default.node_sound_glass_defaults(), + false +) + +stairs.register_slab( + "obsidian_glass", + "default:obsidian_glass", + {cracky = 3}, + {"default_obsidian_glass.png", "default_obsidian_glass.png", "stairs_obsidian_glass_split.png"}, + "Obsidian Glass Slab", + default.node_sound_glass_defaults(), + false +) + +stairs.register_stair_inner( + "obsidian_glass", + "default:obsidian_glass", + {cracky = 3}, + {"stairs_obsidian_glass_stairside.png^[transformR270", "default_obsidian_glass.png", + "stairs_obsidian_glass_stairside.png^[transformFX", "default_obsidian_glass.png", + "default_obsidian_glass.png", "stairs_obsidian_glass_stairside.png"}, + "Obsidian Glass Stair", + default.node_sound_glass_defaults(), + false +) + +stairs.register_stair_outer( + "obsidian_glass", + "default:obsidian_glass", + {cracky = 3}, + {"stairs_obsidian_glass_stairside.png^[transformR90", "default_obsidian_glass.png", + "stairs_obsidian_glass_outer_stairside.png", "stairs_obsidian_glass_stairside.png", + "stairs_obsidian_glass_stairside.png^[transformR90","stairs_obsidian_glass_outer_stairside.png"}, + "Obsidian Glass Stair", + default.node_sound_glass_defaults(), + false +) diff --git a/mods/stairs/license.txt b/mods/stairs/license.txt new file mode 100644 index 0000000..57bd98c --- /dev/null +++ b/mods/stairs/license.txt @@ -0,0 +1,16 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2011-2017 Kahrl +Copyright (C) 2011-2017 celeron55, Perttu Ahola +Copyright (C) 2012-2017 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 diff --git a/mods/stairs/textures/stairs_glass_outer_stairside.png b/mods/stairs/textures/stairs_glass_outer_stairside.png new file mode 100644 index 0000000..9b298c8 Binary files /dev/null and b/mods/stairs/textures/stairs_glass_outer_stairside.png differ diff --git a/mods/stairs/textures/stairs_glass_split.png b/mods/stairs/textures/stairs_glass_split.png new file mode 100644 index 0000000..6287959 Binary files /dev/null and b/mods/stairs/textures/stairs_glass_split.png differ diff --git a/mods/stairs/textures/stairs_glass_stairside.png b/mods/stairs/textures/stairs_glass_stairside.png new file mode 100644 index 0000000..c424294 Binary files /dev/null and b/mods/stairs/textures/stairs_glass_stairside.png differ diff --git a/mods/stairs/textures/stairs_obsidian_glass_outer_stairside.png b/mods/stairs/textures/stairs_obsidian_glass_outer_stairside.png new file mode 100644 index 0000000..63db4a2 Binary files /dev/null and b/mods/stairs/textures/stairs_obsidian_glass_outer_stairside.png differ diff --git a/mods/stairs/textures/stairs_obsidian_glass_split.png b/mods/stairs/textures/stairs_obsidian_glass_split.png new file mode 100644 index 0000000..7647b9b Binary files /dev/null and b/mods/stairs/textures/stairs_obsidian_glass_split.png differ diff --git a/mods/stairs/textures/stairs_obsidian_glass_stairside.png b/mods/stairs/textures/stairs_obsidian_glass_stairside.png new file mode 100644 index 0000000..850f4c6 Binary files /dev/null and b/mods/stairs/textures/stairs_obsidian_glass_stairside.png differ diff --git a/mods/terminal/LICENSE.txt b/mods/terminal/LICENSE.txt new file mode 100644 index 0000000..20d40b6 --- /dev/null +++ b/mods/terminal/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/mods/terminal/depends.txt b/mods/terminal/depends.txt new file mode 100644 index 0000000..5564b38 --- /dev/null +++ b/mods/terminal/depends.txt @@ -0,0 +1,2 @@ +default +beds diff --git a/mods/terminal/init.lua b/mods/terminal/init.lua new file mode 100644 index 0000000..a98985d --- /dev/null +++ b/mods/terminal/init.lua @@ -0,0 +1,343 @@ +-- Terminal mod for Minetest `Glitchtest' game +-- (C) 2018 James Alexander Stevenson +-- GNU GPL 3 + +terminal = {} +local store = minetest.get_mod_storage() + +terminal.display = function(source, user, pos, input) + if not source or not user then + return + end + local pos = pos or user:get_pos() + local input = input or "" + local name = user:get_player_name() + + local cmd_table = { + "+", "broadcast", "bye", "channel", "echo", "guestbook", "help", + "hi", "hint", "info", "list", "name", "set", "sign", "warp", "waypoint", + } + + local term_name, hint, info, wielded, meta + if source == "item" then + wielded = user:get_wielded_item() + meta = wielded:get_meta() + elseif source == "node" then + meta = minetest.get_meta(pos) + elseif source == "mod" then + meta = store + else + return + end + minetest.sound_play("walkie_blip", {object = user}) + + -- Determine input. + input = minetest.formspec_escape(input) + term_name = meta:get_string("term_name") or "default" + hint = "There is no hint." + info = "Welcome to terminal." + + local feedback = "" + + -- Get table with command/args. + local command = input + local args = {} + if command:match("%w") then + for i in command:gmatch"%S+" do + table.insert(args, i) + end + command = args[1] + end + local output = "" + if command == "" then + command = "Yes Master?" + output = "" + feedback = "" + elseif command == "+" then + local new_args = {} + for i = 2, #args do + if type(tonumber(args[i])) == "number" then + new_args[i] = tonumber(args[i]) + else + output = "Err" + break + end + end + command = input + local math = 0 + for _, v in pairs(new_args) do + math = math + v + end + if output ~= "Err" then + output = tostring(math) + end + feedback = "" + elseif command == "say" then + feedback = function() + local chat_message = input:sub(5, -1) + end + elseif command == "broadcast" then + output = "Broadcasting to all players with a walkie talkie on any channel." + feedback = "" + elseif (command == "bye" or + command == "quit" or + command == "exit") then + output = "Shutting down..." + feedback = "" + minetest.after(1, function() + minetest.close_formspec(name, "terminal" .. source .. + minetest.pos_to_string(pos)) + end) + elseif command == "channel" then + local ch = tonumber(args[2]) + if type(ch) == "number" then + --dcbl.channels[name].channel = ch + end + --feedback = "You are on channel " .. tostring(dcbl.channels[name].channel) + feedback = "TODO: Implement chat channels." + elseif command == "echo" then + --[[ + local new_input = input + if new_input:len() >= 40 then + command = new_input:sub(1, 40) .. "$" + else + command = input + end + --]] + if type(args[2]) == "string" then + for i = 2, #args do + if output == "" then + output = args[i] + else + output = output .. " " .. args[i] + end + end + else + output = "Invalid usage, type help echo for more information." + end + feedback = "" + elseif command == "guestbook" then + command = input + output = "Guestbook entries:\n" .. meta:get_string("guestbook") or "" + feedback = "There you go!" + elseif command == "help" then + command = input + if args[2] then + output = "I don't know about " .. args[2] + feedback = "Type help for a list of commands." + else + output = "" + for i = 1, #cmd_table do + output = output .. cmd_table[i] .. " " + end + feedback = "Type help for more information" + end + elseif (command == "hi" or command == "hello") then + output = "Hello." + feedback = "" + elseif command == "hint" then + output = minetest.formspec_escape(hint) + feedback = "" + elseif command == "info" then + output = minetest.formspec_escape(info) + feedback = "" + elseif command == "list" then + local chatters = "" + for _, player in pairs(minetest.get_connected_players()) do + if player:get_inventory():contains_item("main", "walkie:talkie") then + chatters = chatters .. player:get_player_name() .. " " + end + end + if chatters == "" then + output = "No one seems to have a walkie talkie." + else + output = chatters + end + feedback = "Players on channel 1 or near intercomm listed." + elseif command == "name" then + command = input + local args = args[2] + if args then + if args == term_name then + output = "Correct!" + elseif args ~= "" then + meta:set_string("term_name", args) + if source == "item" then + user:set_wielded_item(wielded) + end + output = "Station name is now " .. args + else + output = "Invalid usage. Type help name for more information." + end + else + output = "Station name is " .. term_name + end + feedback = "" + elseif command == "set" then + if args[2] == "warp" then + --[[ + local pt_under = meta:get_string("pt_under") + if not pt_under or pt_under == "" then + return + end + if not args[3] then + return + end + local nn = minetest.string_to_pos(pt_under) + if minetest.get_node(nn).name ~= "warps:warpgoo_amethyst" or + minetest.is_protected(nn, name) then + return + end + minetest.get_meta(nn):set_string("warps_destination", args[3]) + meta:set_string("pt_under", nil) + --]] + feedback = "TODO" + end + feedback = "TODO" + elseif command == "sign" then + command = "Signed:" + local s = "" + for i = 2, 120 do + if not args[i] then + break + end + if s == "" then + s = args[i] + else + s = s .. " " .. args[i] + end + end + meta:set_string("guestbook", s) + if source == "item" then + user:set_wielded_item(wielded) + end + output = s + feedback = "[more]" + elseif command == "warp" then + local user_beds = beds.beds[name] + if user_beds and user_beds[args[2]] then + user:set_pos(user_beds[args[2]]) + end + elseif command == "waypoint" then + output = "set|display" + feedback = "Not yet implemented." + else + output = "Unknown command. Type help for a list." + feedback = "" + end + if type(feedback) == "function" then + return feedback() + end + -- Determine output. + if #output > 40 then + local old_output = output + local spos = 0 + local old_spos = 0 + local ln1 = "" + local ln2 = "" + local ln3 = "" + local new_output + for p in old_output:gmatch"." do + spos = spos + 1 + if spos >= 40 and p == " " and ln1 == "" then + ln1 = old_output:sub(1, spos) + ln2 = old_output:sub(spos + 1, -1) + old_spos = spos + end + if spos >= 80 and p == " " and ln2 ~= "" then + ln2 = old_output:sub(old_spos + 1, spos) + ln3 = old_output:sub(spos + 1, 120) + break + end + end + new_output = ln1 .. "\n" .. ln2 .. "\n" .. ln3 + if old_output:len() > 120 then + output = new_output .. + "\n\n" .. minetest.formspec_escape(feedback) .. + "\n" .. minetest.formspec_escape("[more]") + else + output = new_output .. "\n\n" .. minetest.formspec_escape(feedback) + end + else + output = output .. "\n\n\n\n" .. minetest.formspec_escape(feedback) + end + local fs_command = "label[0,0.1;> " .. command .. "]" + local fs_output = "label[0,0.6;" .. output .. "]" + if command == "echo" then + fs_command = "" + fs_output = "label[0,0.1;" .. output .. "]" + end + + -- Collect data and display. + local formspec = "size[8.8,5.9]" .. + default.gui_bg_img .. + "box[-.1,-.0;8.78,5.1;gray]" .. + fs_command .. + fs_output .. + "field[0.18,5.6;8,1;input;;]" .. + "button[7.78,5.3;1.15,1;ok;OK]" .. + "field_close_on_enter[input;false]" + + if source == "item" then + source = 1 + elseif source == "node" then + source = 2 + elseif source == "mod" then + source = 3 + end + return minetest.show_formspec(name, "terminal" .. source .. + minetest.pos_to_string(pos), formspec) +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname:sub(1, 8) ~= "terminal" or + not player or fields.quit then + return + end + local name = player:get_player_name() + local pos = minetest.string_to_pos(formname:sub(10)) + local source = tonumber(formname:sub(9, 9)) + if fields.ok and fields.input == "" then + return minetest.close_formspec(name, "terminal" .. source .. + minetest.pos_to_string(pos)) + end + local s = {"item", "node", "mod"} + source = s[source] + terminal.display(source, player, pos, fields.input) +end) +--[[ +minetest.register_on_chat_message(function(name, message) + local player = minetest.get_player_by_name(name) + if not player then + return + end + local pp = {} + for _, p in ipairs(minetest.get_connected_players()) do + local n = p:get_player_name() + pp[n] = {} + print(#pp[n]) + end + terminal.display("mod", player, player:get_pos(), "say " .. message) + return true +end) +--]] +---[[ +minetest.register_privilege("terminal", { + description = "Can use /terminal command", + give_to_singleplayer = false, + give_to_admin = true, +}) + +minetest.register_chatcommand("terminal", { + description = "Display terminal interface", + params = "[]", + privs = "terminal", + func = function(name, param) + local player = minetest.get_player_by_name(name) + if not player then + return true, "Invalid usage." + end + terminal.display("mod", player, player:get_pos(), param) + end +}) +--]] diff --git a/mods/tnt/README.txt b/mods/tnt/README.txt new file mode 100644 index 0000000..1970804 --- /dev/null +++ b/mods/tnt/README.txt @@ -0,0 +1,57 @@ +Minetest Game mod: tnt +====================== +See license.txt for license information. + +Authors of source code +---------------------- +PilzAdam (MIT) +ShadowNinja (MIT) +sofar (sofar@foo-projects.org) (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +BlockMen (CC BY-SA 3.0): +All textures not mentioned below. + +ShadowNinja (CC BY-SA 3.0): +tnt_smoke.png + +Wuzzy (CC BY-SA 3.0): +All gunpowder textures except tnt_gunpowder_inventory.png. + +sofar (sofar@foo-projects.org) (CC BY-SA 3.0): +tnt_blast.png + +paramat (CC BY-SA 3.0) +tnt_tnt_stick.png - Derived from a texture by benrob0329. + +Introduction +------------ +This mod adds TNT to Minetest. TNT is a tool to help the player +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 sticks or as a fuse trail for TNT. + +To craft 2 TNT sticks: +G_G +GPG +G_G +G = gunpowder +P = paper +The sticks are not usable as an explosive. + +Craft TNT from 9 TNT sticks. + +There are different ways to ignite TNT: + 1. Hit it with a torch. + 2. Hit a gunpowder fuse trail that leads to TNT with a torch or + flint-and-steel. + 3. Activate it with mesecons (fastest way). + +For 1 TNT: +Node destruction radius is 3 nodes. +Player and object damage radius is 6 nodes. diff --git a/mods/tnt/depends.txt b/mods/tnt/depends.txt new file mode 100644 index 0000000..5ff216f --- /dev/null +++ b/mods/tnt/depends.txt @@ -0,0 +1,3 @@ +default +fire + diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua new file mode 100644 index 0000000..9ab467c --- /dev/null +++ b/mods/tnt/init.lua @@ -0,0 +1,680 @@ +tnt = {} + +-- Default to enabled when in singleplayer +local enable_tnt = minetest.settings:get_bool("enable_tnt") +if enable_tnt == nil then + enable_tnt = minetest.is_singleplayer() +end + +-- loss probabilities array (one in X will be lost) +local loss_prob = {} + +loss_prob["default:cobble"] = 3 +loss_prob["default:dirt"] = 4 + +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 = {} +minetest.after(0, function() + for name, def in pairs(minetest.registered_nodes) do + cid_data[minetest.get_content_id(name)] = { + name = name, + drops = def.drops, + flammable = def.groups.flammable, + on_blast = def.on_blast, + } + end +end) + +local function rand_pos(center, pos, radius) + local def + local reg_nodes = minetest.registered_nodes + local i = 0 + repeat + -- Give up and use the center if this takes too long + if i > 4 then + pos.x, pos.z = center.x, center.z + break + end + pos.x = center.x + math.random(-radius, radius) + pos.z = center.z + math.random(-radius, radius) + def = reg_nodes[minetest.get_node(pos).name] + i = i + 1 + until def and not def.walkable +end + +local function eject_drops(drops, pos, radius) + local drop_pos = vector.new(pos) + for _, item in pairs(drops) do + local count = math.min(item:get_count(), item:get_stack_max()) + while count > 0 do + local take = math.max(1,math.min(radius * radius, + count, + item:get_stack_max())) + rand_pos(pos, drop_pos, radius) + local dropitem = ItemStack(item) + dropitem:set_count(take) + local obj = minetest.add_item(drop_pos, dropitem) + if obj then + obj:get_luaentity().collect = true + obj:set_acceleration({x = 0, y = -10, z = 0}) + obj:set_velocity({x = math.random(-3, 3), + y = math.random(0, 10), + z = math.random(-3, 3)}) + end + count = count - take + end + end +end + +local function add_drop(drops, item) + item = ItemStack(item) + local name = item:get_name() + if loss_prob[name] ~= nil and math.random(1, loss_prob[name]) == 1 then + return + end + + local drop = drops[name] + if drop == nil then + drops[name] = item + else + drop:set_count(drop:get_count() + item:get_count()) + end +end + +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, owner) + if not ignore_protection and minetest.is_protected(npos, owner) then + return cid + end + + local def = cid_data[cid] + + 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 + } + 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, "") + for _, item in pairs(node_drops) do + add_drop(drops, item) + end + return c_air + end +end + +local function calc_velocity(pos1, pos2, old_vel, power) + -- Avoid errors caused by a vector of zero length + if vector.equals(pos1, pos2) then + return old_vel + end + + local vel = vector.direction(pos1, pos2) + vel = vector.normalize(vel) + vel = vector.multiply(vel, power) + + -- Divide by distance + local dist = vector.distance(pos1, pos2) + dist = math.max(dist, 1) + vel = vector.divide(vel, dist) + + -- Add old velocity + vel = vector.add(vel, old_vel) + + -- randomize it a bit + vel = vector.add(vel, { + x = math.random() - 0.5, + y = math.random() - 0.5, + z = math.random() - 0.5, + }) + + -- Limit to terminal velocity + dist = vector.length(vel) + if dist > 250 then + vel = vector.divide(vel, dist / 250) + end + return vel +end + +local function entity_physics(pos, radius, drops) + local objs = minetest.get_objects_inside_radius(pos, radius) + for _, obj in pairs(objs) do + local obj_pos = obj:get_pos() + local dist = math.max(1, vector.distance(pos, obj_pos)) + + local damage = (4 / dist) * radius + if obj:is_player() then + -- currently the engine has no method to set + -- player velocity. See #2960 + -- instead, we knock the player back 1.0 node, and slightly upwards + local dir = vector.normalize(vector.subtract(obj_pos, pos)) + local moveoff = vector.multiply(dir, dist + 1.0) + local newpos = vector.add(pos, moveoff) + newpos = vector.add(newpos, {x = 0, y = 0.2, z = 0}) + obj:set_pos(newpos) + + obj:set_hp(obj:get_hp() - damage) + else + local do_damage = true + local do_knockback = true + local entity_drops = {} + local luaobj = obj:get_luaentity() + local objdef = minetest.registered_entities[luaobj.name] + + if objdef and objdef.on_blast then + do_damage, do_knockback, entity_drops = objdef.on_blast(luaobj, damage) + end + + if do_knockback then + local obj_vel = obj:get_velocity() + obj:set_velocity(calc_velocity(pos, obj_pos, + obj_vel, radius * 10)) + end + if do_damage then + if not obj:get_armor_groups().immortal then + obj:punch(obj, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, nil) + end + end + for _, item in pairs(entity_drops) do + add_drop(drops, item) + end + end + end +end + +local function add_effects(pos, radius, drops) + minetest.add_particle({ + pos = pos, + velocity = vector.new(), + acceleration = vector.new(), + expirationtime = 0.4, + size = radius * 10, + collisiondetection = false, + vertical = false, + texture = "tnt_boom.png", + glow = 15, + }) + minetest.add_particlespawner({ + amount = 64, + time = 0.5, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x = -10, y = -10, z = -10}, + maxvel = {x = 10, y = 10, z = 10}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = 1, + maxexptime = 2.5, + minsize = radius * 3, + maxsize = radius * 5, + texture = "tnt_smoke.png", + }) + + -- we just dropped some items. Look at the items entities and pick + -- one of them to use as texture + local texture = "tnt_blast.png" --fallback texture + local most = 0 + for name, stack in pairs(drops) do + local count = stack:get_count() + if count > most then + most = count + local def = minetest.registered_nodes[name] + if def and def.tiles and def.tiles[1] then + texture = def.tiles[1] + end + end + end + + minetest.add_particlespawner({ + amount = 64, + time = 0.1, + minpos = vector.subtract(pos, radius / 2), + maxpos = vector.add(pos, radius / 2), + minvel = {x = -3, y = 0, z = -3}, + maxvel = {x = 3, y = 5, z = 3}, + minacc = {x = 0, y = -10, z = 0}, + maxacc = {x = 0, y = -10, z = 0}, + minexptime = 0.8, + maxexptime = 2.0, + minsize = radius * 0.66, + maxsize = radius * 2, + texture = texture, + collisiondetection = true, + }) +end + +function tnt.burn(pos, nodename) + local name = nodename or minetest.get_node(pos).name + 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.swap_node(pos, {name = name .. "_burning"}) + minetest.sound_play("tnt_ignite", {pos = pos}) + minetest.get_node_timer(pos):start(1) + end +end + +local function tnt_explode(pos, radius, ignore_protection, ignore_on_blast, owner, explode_center) + pos = vector.round(pos) + -- scan for adjacent TNT nodes first, and enlarge the explosion + local vm1 = VoxelManip() + local p1 = vector.subtract(pos, 2) + local p2 = vector.add(pos, 2) + local minp, maxp = vm1:read_from_map(p1, p2) + local a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + local data = vm1:get_data() + local count = 0 + local c_tnt = minetest.get_content_id("tnt:tnt") + local c_tnt_burning = minetest.get_content_id("tnt:tnt_burning") + local c_tnt_boom = minetest.get_content_id("tnt:boom") + local c_air = minetest.get_content_id("air") + -- make sure we still have explosion even when centre node isnt tnt related + if explode_center then + count = 1 + end + + for z = pos.z - 2, pos.z + 2 do + for y = pos.y - 2, pos.y + 2 do + local vi = a:index(pos.x - 2, y, z) + for x = pos.x - 2, pos.x + 2 do + local cid = data[vi] + if cid == c_tnt or cid == c_tnt_boom or cid == c_tnt_burning then + count = count + 1 + data[vi] = c_air + end + vi = vi + 1 + end + end + end + + vm1:set_data(data) + vm1:write_to_map() + + -- recalculate new radius + radius = math.floor(radius * math.pow(count, 1/3)) + + -- perform the explosion + local vm = VoxelManip() + local pr = PseudoRandom(os.time()) + p1 = vector.subtract(pos, radius) + p2 = vector.add(pos, radius) + minp, maxp = vm:read_from_map(p1, p2) + a = VoxelArea:new({MinEdge = minp, MaxEdge = maxp}) + data = vm:get_data() + + 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 + for y = -radius, radius do + local vi = a:index(pos.x + (-radius), pos.y + y, pos.z + z) + for x = -radius, radius do + local r = vector.length(vector.new(x, y, z)) + if (radius * radius) / (r * r) >= (pr:next(80, 125) / 100) then + local cid = data[vi] + 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, on_construct_queue, + ignore_protection, ignore_on_blast, owner) + end + end + vi = vi + 1 + end + end + end + + vm:set_data(data) + vm:write_to_map() + vm:update_map() + vm:update_liquids() + + -- call check_single_for_falling for everything within 1.5x blast radius + for y = -radius * 1.5, radius * 1.5 do + for z = -radius * 1.5, radius * 1.5 do + for x = -radius * 1.5, radius * 1.5 do + local rad = {x = x, y = y, z = z} + local s = vector.add(pos, rad) + local r = vector.length(rad) + if r / radius < 1.4 then + minetest.check_single_for_falling(s) + end + end + end + end + + for _, queued_data in pairs(on_blast_queue) do + local dist = math.max(1, vector.distance(queued_data.pos, pos)) + local intensity = (radius * radius) / (dist * dist) + local node_drops = queued_data.on_blast(queued_data.pos, intensity) + if node_drops then + for _, item in pairs(node_drops) do + add_drop(drops, item) + end + end + end + + for _, queued_data in pairs(on_construct_queue) do + queued_data.fn(queued_data.pos) + end + + --[[minetest.log("action", "TNT owned by " .. owner .. " detonated at " .. + minetest.pos_to_string(pos) .. " with radius " .. radius)]] + + return drops, radius +end + +function tnt.boom(pos, def) + def = def or {} + def.radius = def.radius or 1 + def.damage_radius = def.damage_radius or def.radius * 2 + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + if not def.explode_center then + minetest.set_node(pos, {name = "tnt:boom"}) + end + local sound = def.sound or "tnt_explode" + minetest.sound_play(sound, {pos = pos, gain = 0.95, + max_hear_distance = math.min(def.radius * 20, 128)}) + local drops, radius = tnt_explode(pos, def.radius, def.ignore_protection, + def.ignore_on_blast, owner, def.explode_center) + -- append entity drops + local damage_radius = (radius / math.max(1, def.radius)) * def.damage_radius + entity_physics(pos, damage_radius, drops) + if not def.disable_drops then + 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", { + drawtype = "airlike", + light_source = default.LIGHT_MAX, + walkable = false, + drop = "", + groups = {dig_immediate = 3}, + -- unaffected by explosions + on_blast = function() end, +}) + +minetest.register_node("tnt:gunpowder", { + description = "Gun Powder", + drawtype = "raillike", + paramtype = "light", + 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" + }, + inventory_image = "tnt_gunpowder_inventory.png", + wield_image = "tnt_gunpowder_inventory.png", + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2}, + }, + groups = {dig_immediate = 2, attached_node = 1, flammable = 5, + connect_to_raillike = minetest.raillike_group("gunpowder")}, + sounds = default.node_sound_leaves_defaults(), + + 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) + minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) + end, + on_burn = function(pos) + minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) + end, + on_ignite = function(pos, igniter) + minetest.set_node(pos, {name = "tnt:gunpowder_burning"}) + end, +}) + +minetest.register_node("tnt:gunpowder_burning", { + drawtype = "raillike", + paramtype = "light", + sunlight_propagates = true, + walkable = false, + light_source = 5, + tiles = {{ + name = "tnt_gunpowder_burning_straight_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }, + { + name = "tnt_gunpowder_burning_curved_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }, + { + name = "tnt_gunpowder_burning_t_junction_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }, + { + name = "tnt_gunpowder_burning_crossing_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }}, + selection_box = { + type = "fixed", + 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") + }, + sounds = default.node_sound_leaves_defaults(), + on_timer = function(pos, elapsed) + for dx = -1, 1 do + for dz = -1, 1 do + if math.abs(dx) + math.abs(dz) == 1 then + for dy = -1, 1 do + tnt.burn({ + x = pos.x + dx, + y = pos.y + dy, + z = pos.z + dz, + }) + end + end + end + end + minetest.remove_node(pos) + end, + -- unaffected by explosions + on_blast = function() end, + on_construct = function(pos) + minetest.sound_play("tnt_gunpowder_burning", {pos = pos, gain = 0.67}) + minetest.get_node_timer(pos):start(1) + end, +}) + +minetest.register_craft({ + output = "tnt:gunpowder 5", + type = "shapeless", + recipe = {"default:coal_lump", "default:gravel"} +}) + +minetest.register_craftitem("tnt:tnt_stick", { + description = "TNT Stick", + inventory_image = "tnt_tnt_stick.png", + groups = {flammable = 5}, +}) + +if enable_tnt then + minetest.register_craft({ + output = "tnt:tnt_stick 2", + recipe = { + {"tnt:gunpowder", "", "tnt:gunpowder"}, + {"tnt:gunpowder", "default:paper", "tnt:gunpowder"}, + {"tnt:gunpowder", "", "tnt:gunpowder"}, + } + }) + + minetest.register_craft({ + output = "tnt:tnt", + recipe = { + {"tnt:tnt_stick", "tnt:tnt_stick", "tnt:tnt_stick"}, + {"tnt:tnt_stick", "tnt:tnt_stick", "tnt:tnt_stick"}, + {"tnt:tnt_stick", "tnt:tnt_stick", "tnt:tnt_stick"} + } + }) + + minetest.register_abm({ + label = "TNT ignition", + nodenames = {"group:tnt", "tnt:gunpowder"}, + neighbors = {"fire:basic_flame", "default:lava_source", "default:lava_flowing"}, + interval = 4, + chance = 1, + action = function(pos, node) + tnt.burn(pos, node.name) + end, + }) +end + +function tnt.register_tnt(def) + local name + if not def.name:find(':') then + name = "tnt:" .. def.name + else + name = def.name + def.name = def.name:match(":([%w_]+)") + end + if not def.tiles then def.tiles = {} end + local tnt_top = def.tiles.top or def.name .. "_top.png" + local tnt_bottom = def.tiles.bottom or def.name .. "_bottom.png" + local tnt_side = def.tiles.side or def.name .. "_side.png" + local tnt_burning = def.tiles.burning or def.name .. "_top_burning_animated.png" + if not def.damage_radius then def.damage_radius = def.radius * 2 end + + if enable_tnt then + minetest.register_node(":" .. name, { + description = def.description, + tiles = {tnt_top, tnt_bottom, tnt_side}, + is_ground_content = false, + groups = {dig_immediate = 2, mesecon = 2, tnt = 1, flammable = 5}, + sounds = default.node_sound_wood_defaults(), + after_place_node = function(pos, placer) + if placer:is_player() then + local meta = minetest.get_meta(pos) + meta:set_string("owner", placer:get_player_name()) + end + end, + on_punch = function(pos, node, puncher) + if puncher:get_wielded_item():get_name() == "default:torch" then + minetest.swap_node(pos, {name = name .. "_burning"}) + minetest.registered_nodes[name .. "_burning"].on_construct(pos) + --[[minetest.log("action", puncher:get_player_name() .. + " ignites " .. node.name .. " at " .. + minetest.pos_to_string(pos))]] + end + end, + on_blast = function(pos, intensity) + minetest.after(0.1, function() + tnt.boom(pos, def) + end) + end, + mesecons = {effector = + {action_on = + function(pos) + tnt.boom(pos, def) + end + } + }, + on_burn = function(pos) + minetest.swap_node(pos, {name = name .. "_burning"}) + minetest.registered_nodes[name .. "_burning"].on_construct(pos) + end, + on_ignite = function(pos, igniter) + minetest.swap_node(pos, {name = name .. "_burning"}) + minetest.registered_nodes[name .. "_burning"].on_construct(pos) + end, + }) + end + + minetest.register_node(":" .. name .. "_burning", { + tiles = { + { + name = tnt_burning, + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + } + }, + tnt_bottom, tnt_side + }, + light_source = 5, + drop = "", + sounds = default.node_sound_wood_defaults(), + groups = {falling_node = 1}, + on_timer = function(pos, elapsed) + tnt.boom(pos, def) + end, + -- unaffected by explosions + on_blast = function() end, + on_construct = function(pos) + minetest.sound_play("tnt_ignite", {pos = pos}) + minetest.get_node_timer(pos):start(4) + minetest.check_for_falling(pos) + end, + }) +end + +tnt.register_tnt({ + name = "tnt:tnt", + description = "TNT", + radius = tnt_radius, +}) diff --git a/mods/tnt/license.txt b/mods/tnt/license.txt new file mode 100644 index 0000000..2c57df3 --- /dev/null +++ b/mods/tnt/license.txt @@ -0,0 +1,66 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2014-2016 PilzAdam +Copyright (C) 2014-2016 ShadowNinja +Copyright (C) 2016 sofar (sofar@foo-projects.org) +Copyright (C) 2014-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2014-2016 ShadowNinja +Copyright (C) 2015-2016 Wuzzy +Copyright (C) 2016 sofar (sofar@foo-projects.org) +Copyright (C) 2018 paramat + +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/tnt/sounds/tnt_explode.ogg b/mods/tnt/sounds/tnt_explode.ogg new file mode 100644 index 0000000..a414ea0 Binary files /dev/null and b/mods/tnt/sounds/tnt_explode.ogg differ diff --git a/mods/tnt/sounds/tnt_gunpowder_burning.ogg b/mods/tnt/sounds/tnt_gunpowder_burning.ogg new file mode 100644 index 0000000..5c5bfaf Binary files /dev/null and b/mods/tnt/sounds/tnt_gunpowder_burning.ogg differ diff --git a/mods/tnt/sounds/tnt_ignite.ogg b/mods/tnt/sounds/tnt_ignite.ogg new file mode 100644 index 0000000..199f206 Binary files /dev/null and b/mods/tnt/sounds/tnt_ignite.ogg differ diff --git a/mods/tnt/textures/tnt_blast.png b/mods/tnt/textures/tnt_blast.png new file mode 100644 index 0000000..bbb1096 Binary files /dev/null and b/mods/tnt/textures/tnt_blast.png differ diff --git a/mods/tnt/textures/tnt_boom.png b/mods/tnt/textures/tnt_boom.png new file mode 100644 index 0000000..c848bfc Binary files /dev/null and b/mods/tnt/textures/tnt_boom.png differ diff --git a/mods/tnt/textures/tnt_bottom.png b/mods/tnt/textures/tnt_bottom.png new file mode 100644 index 0000000..95f66cb Binary files /dev/null and b/mods/tnt/textures/tnt_bottom.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_burning_crossing_animated.png b/mods/tnt/textures/tnt_gunpowder_burning_crossing_animated.png new file mode 100644 index 0000000..a901f7b Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_burning_crossing_animated.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_burning_curved_animated.png b/mods/tnt/textures/tnt_gunpowder_burning_curved_animated.png new file mode 100644 index 0000000..bc01806 Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_burning_curved_animated.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_burning_straight_animated.png b/mods/tnt/textures/tnt_gunpowder_burning_straight_animated.png new file mode 100644 index 0000000..c860ace Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_burning_straight_animated.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_burning_t_junction_animated.png b/mods/tnt/textures/tnt_gunpowder_burning_t_junction_animated.png new file mode 100644 index 0000000..a556072 Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_burning_t_junction_animated.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_crossing.png b/mods/tnt/textures/tnt_gunpowder_crossing.png new file mode 100644 index 0000000..916c84e Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_crossing.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_curved.png b/mods/tnt/textures/tnt_gunpowder_curved.png new file mode 100644 index 0000000..cb8b4ea Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_curved.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_inventory.png b/mods/tnt/textures/tnt_gunpowder_inventory.png new file mode 100644 index 0000000..105a2d2 Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_inventory.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_straight.png b/mods/tnt/textures/tnt_gunpowder_straight.png new file mode 100644 index 0000000..8ab0e3c Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_straight.png differ diff --git a/mods/tnt/textures/tnt_gunpowder_t_junction.png b/mods/tnt/textures/tnt_gunpowder_t_junction.png new file mode 100644 index 0000000..ac997a7 Binary files /dev/null and b/mods/tnt/textures/tnt_gunpowder_t_junction.png differ diff --git a/mods/tnt/textures/tnt_side.png b/mods/tnt/textures/tnt_side.png new file mode 100644 index 0000000..d303473 Binary files /dev/null and b/mods/tnt/textures/tnt_side.png differ diff --git a/mods/tnt/textures/tnt_smoke.png b/mods/tnt/textures/tnt_smoke.png new file mode 100644 index 0000000..488b50f Binary files /dev/null and b/mods/tnt/textures/tnt_smoke.png differ diff --git a/mods/tnt/textures/tnt_tnt_stick.png b/mods/tnt/textures/tnt_tnt_stick.png new file mode 100644 index 0000000..bc47a29 Binary files /dev/null and b/mods/tnt/textures/tnt_tnt_stick.png differ diff --git a/mods/tnt/textures/tnt_top.png b/mods/tnt/textures/tnt_top.png new file mode 100644 index 0000000..31b807c Binary files /dev/null and b/mods/tnt/textures/tnt_top.png differ diff --git a/mods/tnt/textures/tnt_top_burning.png b/mods/tnt/textures/tnt_top_burning.png new file mode 100644 index 0000000..fc0d490 Binary files /dev/null and b/mods/tnt/textures/tnt_top_burning.png differ diff --git a/mods/tnt/textures/tnt_top_burning_animated.png b/mods/tnt/textures/tnt_top_burning_animated.png new file mode 100644 index 0000000..18a270f Binary files /dev/null and b/mods/tnt/textures/tnt_top_burning_animated.png differ diff --git a/mods/vessels/README.txt b/mods/vessels/README.txt new file mode 100644 index 0000000..a54e330 --- /dev/null +++ b/mods/vessels/README.txt @@ -0,0 +1,22 @@ +Minetest Game mod: vessels +========================== +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Vanessa Ezekowitz (LGPLv2.1+) +Modified by Perttu Ahola (LGPLv2.1+) +Various Minetest developers and contributors (LGPLv2.1+) + +Authors of media (textures) +--------------------------- +All not listed below, Vanessa Ezekowitz (CC BY-SA 3.0) + +The following textures were modified by Thomas-S (CC BY-SA 3.0): + vessels_drinking_glass.png + vessels_drinking_glass_inv.png + vessels_glass_bottle.png + vessels_steel_bottle.png + +The following texture was created by Wuzzy (CC BY-SA 3.0): + vessels_shelf_slot.png (based on vessels_glass_bottle.png) diff --git a/mods/vessels/depends.txt b/mods/vessels/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/vessels/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/vessels/init.lua b/mods/vessels/init.lua new file mode 100644 index 0000000..43d8092 --- /dev/null +++ b/mods/vessels/init.lua @@ -0,0 +1,216 @@ +-- Minetest 0.4 mod: vessels +-- See README.txt for licensing and other information. + +local vessels_shelf_formspec = + "size[8,7;]" .. + default.gui_bg .. + default.gui_bg_img .. + default.gui_slots .. + "list[context;vessels;0,0.3;8,2;]" .. + "list[current_player;main;0,2.85;8,1;]" .. + "list[current_player;main;0,4.08;8,3;8]" .. + "listring[context;vessels]" .. + "listring[current_player;main]" .. + default.get_hotbar_bg(0, 2.85) + +local function get_vessels_shelf_formspec(inv) + local formspec = vessels_shelf_formspec + local invlist = inv and inv:get_list("vessels") + -- Inventory slots overlay + local vx, vy = 0, 0.3 + for i = 1, 16 do + if i == 9 then + vx = 0 + vy = vy + 1 + end + if not invlist or invlist[i]:is_empty() then + formspec = formspec .. + "image[" .. vx .. "," .. vy .. ";1,1;vessels_shelf_slot.png]" + end + vx = vx + 1 + end + return formspec +end + +minetest.register_node("vessels:shelf", { + description = "Vessels Shelf", + tiles = {"default_wood.png", "default_wood.png", "default_wood.png", + "default_wood.png", "vessels_shelf.png", "vessels_shelf.png"}, + paramtype2 = "facedir", + is_ground_content = false, + groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3}, + sounds = default.node_sound_wood_defaults(), + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", get_vessels_shelf_formspec(nil)) + local inv = meta:get_inventory() + inv:set_size("vessels", 8 * 2) + end, + can_dig = function(pos,player) + local inv = minetest.get_meta(pos):get_inventory() + return inv:is_empty("vessels") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if minetest.get_item_group(stack:get_name(), "vessel") ~= 0 then + return stack:get_count() + end + return 0 + end, + 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 vessels shelf at ".. minetest.pos_to_string(pos)) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", get_vessels_shelf_formspec(meta:get_inventory())) + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.log("action", player:get_player_name() .. + " moves stuff to vessels shelf at ".. minetest.pos_to_string(pos)) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", get_vessels_shelf_formspec(meta:get_inventory())) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + minetest.log("action", player:get_player_name() .. + " takes stuff from vessels shelf at ".. minetest.pos_to_string(pos)) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", get_vessels_shelf_formspec(meta:get_inventory())) + end, + on_blast = function(pos) + local drops = {} + default.get_inventory_drops(pos, "vessels", drops) + drops[#drops + 1] = "vessels:shelf" + minetest.remove_node(pos) + return drops + end, +}) + +minetest.register_craft({ + output = "vessels:shelf", + recipe = { + {"group:wood", "group:wood", "group:wood"}, + {"group:vessel", "group:vessel", "group:vessel"}, + {"group:wood", "group:wood", "group:wood"}, + } +}) + +minetest.register_node("vessels:glass_bottle", { + description = "Empty Glass Bottle", + drawtype = "plantlike", + tiles = {"vessels_glass_bottle.png"}, + inventory_image = "vessels_glass_bottle.png", + wield_image = "vessels_glass_bottle.png", + paramtype = "light", + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + groups = {vessel = 1, dig_immediate = 3, attached_node = 1}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_craft( { + output = "vessels:glass_bottle 10", + recipe = { + {"default:glass", "", "default:glass"}, + {"default:glass", "", "default:glass"}, + {"", "default:glass", ""} + } +}) + +minetest.register_node("vessels:drinking_glass", { + description = "Empty Drinking Glass", + drawtype = "plantlike", + tiles = {"vessels_drinking_glass.png"}, + inventory_image = "vessels_drinking_glass_inv.png", + wield_image = "vessels_drinking_glass.png", + paramtype = "light", + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + groups = {vessel = 1, dig_immediate = 3, attached_node = 1}, + sounds = default.node_sound_glass_defaults(), +}) + +minetest.register_craft( { + output = "vessels:drinking_glass 14", + recipe = { + {"default:glass", "", "default:glass"}, + {"default:glass", "", "default:glass"}, + {"default:glass", "default:glass", "default:glass"} + } +}) + +minetest.register_node("vessels:steel_bottle", { + description = "Empty Heavy Steel Bottle", + drawtype = "plantlike", + tiles = {"vessels_steel_bottle.png"}, + inventory_image = "vessels_steel_bottle.png", + wield_image = "vessels_steel_bottle.png", + paramtype = "light", + is_ground_content = false, + walkable = false, + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.3, 0.25} + }, + groups = {vessel = 1, dig_immediate = 3, attached_node = 1}, + sounds = default.node_sound_defaults(), +}) + +minetest.register_craft( { + output = "vessels:steel_bottle 5", + recipe = { + {"default:steel_ingot", "", "default:steel_ingot"}, + {"default:steel_ingot", "", "default:steel_ingot"}, + {"", "default:steel_ingot", ""} + } +}) + + +-- Glass and steel recycling + +minetest.register_craftitem("vessels:glass_fragments", { + description = "Glass Fragments", + inventory_image = "vessels_glass_fragments.png", +}) + +minetest.register_craft( { + type = "shapeless", + output = "vessels:glass_fragments", + recipe = { + "vessels:glass_bottle", + "vessels:glass_bottle", + }, +}) + +minetest.register_craft( { + type = "shapeless", + output = "vessels:glass_fragments", + recipe = { + "vessels:drinking_glass", + "vessels:drinking_glass", + }, +}) + +minetest.register_craft({ + type = "cooking", + output = "default:glass", + recipe = "vessels:glass_fragments", +}) + +minetest.register_craft( { + type = "cooking", + output = "default:steel_ingot", + recipe = "vessels:steel_bottle", +}) + +minetest.register_craft({ + type = "fuel", + recipe = "vessels:shelf", + burntime = 30, +}) diff --git a/mods/vessels/license.txt b/mods/vessels/license.txt new file mode 100644 index 0000000..de16a3b --- /dev/null +++ b/mods/vessels/license.txt @@ -0,0 +1,52 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2012-2016 Vanessa Ezekowitz +Copyright (C) 2012-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 Vanessa Ezekowitz +Copyright (C) 2016 Thomas-S + +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/vessels/textures/vessels_drinking_glass.png b/mods/vessels/textures/vessels_drinking_glass.png new file mode 100644 index 0000000..d5037b8 Binary files /dev/null and b/mods/vessels/textures/vessels_drinking_glass.png differ diff --git a/mods/vessels/textures/vessels_drinking_glass_inv.png b/mods/vessels/textures/vessels_drinking_glass_inv.png new file mode 100644 index 0000000..9992bd9 Binary files /dev/null and b/mods/vessels/textures/vessels_drinking_glass_inv.png differ diff --git a/mods/vessels/textures/vessels_glass_bottle.png b/mods/vessels/textures/vessels_glass_bottle.png new file mode 100644 index 0000000..6ea37db Binary files /dev/null and b/mods/vessels/textures/vessels_glass_bottle.png differ diff --git a/mods/vessels/textures/vessels_glass_fragments.png b/mods/vessels/textures/vessels_glass_fragments.png new file mode 100644 index 0000000..7c6c488 Binary files /dev/null and b/mods/vessels/textures/vessels_glass_fragments.png differ diff --git a/mods/vessels/textures/vessels_shelf.png b/mods/vessels/textures/vessels_shelf.png new file mode 100644 index 0000000..87c69b2 Binary files /dev/null and b/mods/vessels/textures/vessels_shelf.png differ diff --git a/mods/vessels/textures/vessels_shelf_slot.png b/mods/vessels/textures/vessels_shelf_slot.png new file mode 100644 index 0000000..ff29082 Binary files /dev/null and b/mods/vessels/textures/vessels_shelf_slot.png differ diff --git a/mods/vessels/textures/vessels_steel_bottle.png b/mods/vessels/textures/vessels_steel_bottle.png new file mode 100644 index 0000000..61d3071 Binary files /dev/null and b/mods/vessels/textures/vessels_steel_bottle.png differ diff --git a/mods/walkie/README b/mods/walkie/README new file mode 100644 index 0000000..38e3ac3 --- /dev/null +++ b/mods/walkie/README @@ -0,0 +1,3 @@ +Walkie Talkie mods for Minetest + +Wield the Walkie Talkie to display a compass with coordinates on screen. diff --git a/mods/walkie/depends.txt b/mods/walkie/depends.txt new file mode 100644 index 0000000..f9b9df0 --- /dev/null +++ b/mods/walkie/depends.txt @@ -0,0 +1 @@ +terminal diff --git a/mods/walkie/init.lua b/mods/walkie/init.lua new file mode 100644 index 0000000..4a31d3d --- /dev/null +++ b/mods/walkie/init.lua @@ -0,0 +1,272 @@ +--[[ Walkie Talkie Minetest Mod (Part of Glitchtest Game) + Copyright (C) 2018 James A. Stevenson + GNU GPL 3 ]] + +walkie = {} +walkie.players = {} +walkie.meters = {} + +local hud_elem_compass = { + hud_elem_type = "image", + position = {x = 1, y = 1}, + name = "Compass", + scale = {x = 1, y = 1}, + text = "walkie_empty.png", + alignment = {x = -1, y = -1}, + offset = {x = -20, y = -156}, +} + +local hud_elem_coords = { + hud_elem_type = "text", + position = {x = 1, y = 1}, + name = "Coordinates", + scale = {x = 200, y = 20}, + text = "", + number = 0xFFFFFF, + direction = 1, + alignment = {x = -1, y = -1}, + offset = {x = -20, y = -136}, +} + +local hud_elem_waypoint = { + hud_elem_type = "waypoint", + name = "", + text = "", + number = 0xFFFFFF, +} + +local function updater(player) + if not player then + return + end + local name = player:get_player_name() + if not walkie.players[name] then + return + end + local wielded_name = player:get_wielded_item():get_name() + if wielded_name == "walkie:talkie" then + -- Show compass & coordinates. + walkie.players[name].pos = player:get_pos() + walkie.players[name].dir = player:get_look_horizontal() + local p = vector.round(walkie.players[name].pos) + local d = math.floor(walkie.players[name].dir * math.pi) + if d >= 1 and d < 4 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_nw.png") + elseif d >= 4 and d < 6 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_n.png^[transformR270") + elseif d >= 6 and d < 9 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_nw.png^[transformR270") + elseif d >= 9 and d < 11 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_n.png^[transformR180") + elseif d >= 11 and d < 14 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_nw.png^[transformR180") + elseif d >= 14 and d < 16 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_n.png^[transformR90") + elseif d >= 16 and d < 19 then + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_nw.png^[transformR90") + else + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_compass_n.png") + end + player:hud_change(walkie.meters[name].coords, + "text", + p.x .. ", " .. p.y .. ", " .. p.z) + player:set_properties({zoom_fov = 45}) + player:hud_set_flags({minimap = true, minimap_radar = true}) + -- Add waypoint HUD. + if not walkie.meters[name].waypoint and + walkie.players[name].waypoints.pos then + local pos = walkie.players[name].waypoints.pos + if pos then + local hud_def = hud_elem_waypoint + hud_def.world_pos = pos + local id = player:hud_add(hud_def) + walkie.meters[name].waypoint = id + end + end + else + player:hud_set_flags({minimap = false, minimap_radar = false}) + -- "Remove" compass and coordinate HUDs. + player:hud_change(walkie.meters[name].coords, + "text", + "") + player:hud_change(walkie.meters[name].compass, + "text", + "walkie_empty.png") + -- Remove waypoints HUD. + if walkie.meters[name].waypoint then + player:hud_remove(walkie.meters[name].waypoint) + player:set_properties({zoom_fov = 0}) + player:hud_set_flags({minimap = false, minimap_radar = false}) + walkie.meters[name].waypoint = nil + end + end + minetest.after(0.12, updater, player) +end + +minetest.register_on_joinplayer(function(player) + if not player then + return + end + local name = player:get_player_name() + local compass = player:hud_add(hud_elem_compass) + local coords = player:hud_add(hud_elem_coords) + walkie.meters[name] = { + compass = compass, + coords = coords, + } + walkie.players[name] = {waypoints = {}} + local waypoints = minetest.deserialize(player:get_attribute("waypoints")) + if waypoints then + walkie.players[name].waypoints = waypoints + end + updater(player) +end) + +minetest.register_on_leaveplayer(function(player) + if not player then + return + end + local name = player:get_player_name() + walkie.players[name] = nil + walkie.meters[name] = nil +end) + +minetest.register_on_dieplayer(function(player) + if not player then + return + end + local name = player:get_player_name() + local pos = player:get_pos() + if not walkie.players[name] then --TODO Move to respawn? + return + end + walkie.players[name].waypoints.death = pos + walkie.players[name].waypoints.pos = pos + player:hud_change(walkie.meters[name].waypoint, "world_pos", pos) + player:set_attribute("waypoints", + minetest.serialize(walkie.players[name].waypoints)) +end) + +-- Walkie Talkie +minetest.register_craftitem("walkie:talkie", { + description = "Walkie Talkie", + inventory_image = "walkie_talkie.png", + stack_max = 1, + on_use = function(itemstack, user, pointed_thing) + local sound = minetest.sound_play({name = "walkie_blip", gain = 0.667}, + {object = user, loop = true}) + minetest.after(0.1, function () + minetest.sound_stop(sound) + end) + + local name = user:get_player_name() + local pos = user:get_pos() + local waypoint = walkie.players[name].waypoints.pos + if waypoint then + local saved = walkie.players[name].waypoints.saved + local death = walkie.players[name].waypoints.death + if waypoint == saved and death then + walkie.players[name].waypoints.pos = death + user:hud_change(walkie.meters[name].waypoint, + "world_pos", death) + elseif waypoint == death and saved then + walkie.players[name].waypoints.pos = saved + user:hud_change(walkie.meters[name].waypoint, + "world_pos", saved) + end + end + return itemstack + end, + on_place = function(itemstack, placer, pointed_thing) + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + local pdef = minetest.registered_nodes[node.name] + if node.name == "walkie:intercomm" then + local pos = placer:get_pos() + local name = placer:get_player_name() + walkie.players[name].waypoints.saved = pos + walkie.players[name].waypoints.pos = pos + placer:hud_change(walkie.meters[name].waypoint, + "world_pos", pos) + placer:set_attribute("waypoints", + minetest.serialize(walkie.players[name].waypoints)) + elseif pdef and pdef.on_rightclick then + return pdef.on_rightclick(pointed_thing.under, + node, placer, itemstack, pointed_thing) + else + terminal.display("item", placer) + end + end + end, + on_secondary_use = function(itemstack, user, pointed_thing) + terminal.display("item", user) +end, +}) + +-- Intercomm +minetest.register_node("walkie:intercomm", { + description = "Intercomm", + drawtype = "nodebox", + tiles = {"walkie_intercomm_wall.png"}, + inventory_image = "walkie_intercomm.png", + wield_image = "walkie_intercomm.png", + paramtype = "light", + paramtype2 = "wallmounted", + sunlight_propagates = true, + is_ground_content = false, + stack_max = 1, + light_source = 8, + walkable = false, + node_box = { + type = "wallmounted", + wall_top = {-0.4375, 0.5, -0.3125, 0.4375, 0.5, 0.3125}, + wall_bottom = {-0.4375, -0.5, -0.3125, 0.4375, -0.4375, 0.3125}, + wall_side = {-0.5, -0.375, -0.4375, -0.4375, 0.375, 0.4375}, + }, + groups = {cracky = 3, oddly_breakable_by_hand = 1, attached_node = 1}, + legacy_wallmounted = true, + sounds = { + footstep = {name = "default_hard_footstep", gain = 0.5}, + dig = {name = "walkie_blip", gain = 1.0}, + dug = {name = "walkie_blip", gain = 1.0}, + place = {name = "walkie_blip", gain = 1.0}, + place_failed = {name = "walkie_blip", gain = 1.0} + }, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + terminal.display("node", clicker) + end, +}) + +minetest.register_craft({ + output = "walkie:talkie", + recipe = { + {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"}, + {"", "default:mese_crystal", ""}, + {"default:copper_ingot", "default:steel_ingot", "default:copper_ingot"}, + } +}) + +minetest.register_craft({ + output = "walkie:intercomm", + recipe = { + {"default:copper_ingot", "default:mese_crystal", "default:copper_ingot"}, + {"default:steel_ingot", "walkie:talkie", "default:steel_ingot"}, + {"default:copper_ingot", "default:diamond", "default:copper_ingot"}, + } +}) diff --git a/mods/walkie/mod.conf b/mods/walkie/mod.conf new file mode 100644 index 0000000..519dbd3 --- /dev/null +++ b/mods/walkie/mod.conf @@ -0,0 +1 @@ +name = walkie diff --git a/mods/walkie/sounds/walkie_blip.1.ogg b/mods/walkie/sounds/walkie_blip.1.ogg new file mode 100644 index 0000000..baa7d17 Binary files /dev/null and b/mods/walkie/sounds/walkie_blip.1.ogg differ diff --git a/mods/walkie/sounds/walkie_blip.2.ogg b/mods/walkie/sounds/walkie_blip.2.ogg new file mode 100644 index 0000000..698c14c Binary files /dev/null and b/mods/walkie/sounds/walkie_blip.2.ogg differ diff --git a/mods/walkie/sounds/walkie_blip.3.ogg b/mods/walkie/sounds/walkie_blip.3.ogg new file mode 100644 index 0000000..c60e293 Binary files /dev/null and b/mods/walkie/sounds/walkie_blip.3.ogg differ diff --git a/mods/walkie/textures/walkie_compass_n.png b/mods/walkie/textures/walkie_compass_n.png new file mode 100644 index 0000000..6817288 Binary files /dev/null and b/mods/walkie/textures/walkie_compass_n.png differ diff --git a/mods/walkie/textures/walkie_compass_nw.png b/mods/walkie/textures/walkie_compass_nw.png new file mode 100644 index 0000000..08751eb Binary files /dev/null and b/mods/walkie/textures/walkie_compass_nw.png differ diff --git a/mods/walkie/textures/walkie_empty.png b/mods/walkie/textures/walkie_empty.png new file mode 100644 index 0000000..0b800ab Binary files /dev/null and b/mods/walkie/textures/walkie_empty.png differ diff --git a/mods/walkie/textures/walkie_intercomm.png b/mods/walkie/textures/walkie_intercomm.png new file mode 100644 index 0000000..e7e711e Binary files /dev/null and b/mods/walkie/textures/walkie_intercomm.png differ diff --git a/mods/walkie/textures/walkie_intercomm_wall.png b/mods/walkie/textures/walkie_intercomm_wall.png new file mode 100644 index 0000000..f178303 Binary files /dev/null and b/mods/walkie/textures/walkie_intercomm_wall.png differ diff --git a/mods/walkie/textures/walkie_talkie.png b/mods/walkie/textures/walkie_talkie.png new file mode 100644 index 0000000..de43af8 Binary files /dev/null and b/mods/walkie/textures/walkie_talkie.png differ diff --git a/mods/walls/README.txt b/mods/walls/README.txt new file mode 100644 index 0000000..ba33bd7 --- /dev/null +++ b/mods/walls/README.txt @@ -0,0 +1,7 @@ +Minetest Game mod: walls +======================== +See license.txt for license information. + +Authors of source code +---------------------- +Auke Kok (LGPLv2.1+) diff --git a/mods/walls/depends.txt b/mods/walls/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/walls/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/walls/init.lua b/mods/walls/init.lua new file mode 100644 index 0000000..91a89cf --- /dev/null +++ b/mods/walls/init.lua @@ -0,0 +1,50 @@ +walls = {} + +walls.register = function(wall_name, wall_desc, wall_texture_table, wall_mat, wall_sounds) + --make wall_texture_table paramenter backwards compatible for mods passing single texture + if type(wall_texture_table) ~= "table" then + wall_texture_table = { wall_texture_table } + end + -- inventory node, and pole-type wall start item + minetest.register_node(wall_name, { + description = wall_desc, + drawtype = "nodebox", + node_box = { + type = "connected", + fixed = {{-1/4, -1/2, -1/4, 1/4, 1/2, 1/4}}, + -- connect_bottom = + connect_front = {{-3/16, -1/2, -1/2, 3/16, 3/8, -1/4}}, + connect_left = {{-1/2, -1/2, -3/16, -1/4, 3/8, 3/16}}, + connect_back = {{-3/16, -1/2, 1/4, 3/16, 3/8, 1/2}}, + connect_right = {{ 1/4, -1/2, -3/16, 1/2, 3/8, 3/16}}, + }, + connects_to = { "group:wall", "group:stone", "group:fence" }, + paramtype = "light", + is_ground_content = false, + tiles = wall_texture_table, + walkable = true, + groups = { cracky = 3, wall = 1, stone = 2 }, + sounds = wall_sounds, + }) + + -- crafting recipe + minetest.register_craft({ + output = wall_name .. " 6", + recipe = { + { '', '', '' }, + { wall_mat, wall_mat, wall_mat}, + { wall_mat, wall_mat, wall_mat}, + } + }) + +end + +walls.register("walls:cobble", "Cobblestone Wall", {"default_cobble.png"}, + "default:cobble", default.node_sound_stone_defaults()) + +walls.register("walls:mossycobble", "Mossy Cobblestone Wall", {"default_mossycobble.png"}, + "default:mossycobble", default.node_sound_stone_defaults()) + +walls.register("walls:desertcobble", "Desert Cobblestone Wall", {"default_desert_cobble.png"}, + "default:desert_cobble", default.node_sound_stone_defaults()) + diff --git a/mods/walls/license.txt b/mods/walls/license.txt new file mode 100644 index 0000000..ccfaf1c --- /dev/null +++ b/mods/walls/license.txt @@ -0,0 +1,14 @@ +License of source code +---------------------- + +GNU Lesser General Public License, version 2.1 +Copyright (C) 2015 Auke Kok + +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 diff --git a/mods/warps/LICENSE b/mods/warps/LICENSE new file mode 100644 index 0000000..249399b --- /dev/null +++ b/mods/warps/LICENSE @@ -0,0 +1,22 @@ + +warps- a minetest mod that adds more farming crops + +See spdx.org/licenses to see what the License Identifiers used below mean. + +=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + +All source code (lua): + (C) Auke Kok + LGPL-2.1+ + +All textures, models: + (C) Auke Kok + CC-BY-3.0 + +File: warps_woosh.ogg +Original: 112837__dymewiz__whoosh-21.wav +Url: https://www.freesound.org/people/Dymewiz/sounds/112837/ +License: CC-BY-3.0 + +=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~ + diff --git a/mods/warps/README b/mods/warps/README new file mode 100644 index 0000000..211de5c --- /dev/null +++ b/mods/warps/README @@ -0,0 +1,37 @@ + +"Warps" - a simple warp mod for minetest. + +======== + +/setwarp [name] +/delwarp [name] +/warp [name] +/listwarps + +priv: warp_admin - set/change/delete warps +priv: warp_user - list, and use warps + +warps are stored in the world folder file "warps.txt". + +A warpstone can be given or found in the creative inventory (item +id: warps:warpstone). This warpstone can be placed on the ground +and be programmed to warp players who punch it to a certain warp +location (one of the warps in /listwarps). Right-clicking the item +as a warp_admin user will allow you to program the warpstone. The +warpstone can be removed by shift-punching the warp stone. + +All warps are delayed by ~5 seconds. You have to stand still for +that duration, otherwise the warp will be cancelled. This may avoid +warp spamming and warping out of combat a bit. There's a bit +of variation in time due to the timer resolution in minetest +being rather large. + +======== + +Copyright (C) 2015 - Auke Kok + +"warps" 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. + diff --git a/mods/warps/depends.txt b/mods/warps/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/warps/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/warps/description.txt b/mods/warps/description.txt new file mode 100644 index 0000000..b87e447 --- /dev/null +++ b/mods/warps/description.txt @@ -0,0 +1 @@ +Warp locations and warp stones (portal stones) diff --git a/mods/warps/init.lua b/mods/warps/init.lua new file mode 100644 index 0000000..c3d5b87 --- /dev/null +++ b/mods/warps/init.lua @@ -0,0 +1,342 @@ +-- Copyright (C) 2017, 2018 James Stevenson +-- Copyright (C) 2015 - Auke Kok +-- GNU GPL 3 + +local warps = { + mese = "yellow", + --amethyst = "0x542164CC", + diamond = "blue", + --ruby = "red", + --emerald = "emerald", +} + +local function switch_class_fs(player) + local formspec = "size[8,3.5]" .. + jas0.exit_button() .. + jas0.help_button() .. + "button_exit[4.6,1.9;2,1;switch;Switch]" .. + "dropdown[2.7,2;2;class;Mage,Miner,Scout,Node;1]" .. + "" + local meta = player:get_meta() + local class = meta:get("class") + local level = jas0.level(player) + local xp = tostring(level):gsub("(.*)%.", "") + formspec = formspec .. + "label[0,0;Current Stats]" .. + "label[0.34,0.5;Class: " .. class .. "]" .. + "label[0.34,1;Level: " .. tostring(level):gsub("%.(.*)", "") .. "]" .. + "label[0.34,1.5;XP: " .. xp:sub(1, 2) .. "]" .. + "" + return formspec +end + +local selected = {} +local function warp_formspec(name) + local dest = selected[name] + if dest then + dest = minetest.get_meta(dest):get_string("destination") + end + return "size[7.76,2.9]" .. + jas0.exit_button(-0.25, -0.1) .. + "field[1.15,1.2;5.25,1;warp;Destination;" .. dest .. "]" .. + "button_exit[6,0.88;1,1;ok;OK]" .. + "field_close_on_enter[warp;true]" .. + "" +end + +local timer +local on_punch = function(pos, node, puncher, pointed_thing) + if node.name == "warps:warpstone_diamond" then + local meta = minetest.get_meta(pos) + if meta and meta:get_string("warp") ~= "" and + meta:get_string("state") == "" then + local sid = minetest.sound_play("warps_woosh", { + object = puncher, + }) + meta:set_string("state", "timeout") + local warp = minetest.deserialize(meta:get_string("warp")) + local p = puncher:get_pos() + jas0.message(puncher, "Hold still.") + timer = function(p, player, time, meta, sid, warp) + if vector.equals(p, player:get_pos()) then + if time >= 4.4 then + minetest.sound_fade(sid, -1, 0) + meta:set_string("state", "") + player:set_pos(warp) + warp.y = warp.y + 2 + jas0.message(player, "Warped to " .. meta:get_string("destination") .. ".") + return minetest.sound_play("sneak_jump_item", + {pos = warp, max_hear_distance = 64}) + end + minetest.after(0.334, timer, p, player, time + 0.334, meta, sid, warp) + else + jas0.message(puncher, "Stand still for 5 seconds after punching to warp.") + minetest.sound_fade(sid, -0.89, 0) + meta:set_string("state", "") + return + end + end + return timer(p, puncher, 0, meta, sid, warp) + elseif meta:get_string("state") == "timeout" then + jas0.message(puncher, "Waiting.") + else + jas0.message(puncher, "No destination set.") + end + end +end + +local on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + local name = clicker:get_player_name() + selected[name] = pos + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + if node.name == "warps:warpstone_diamond" then + if name ~= owner then + jas0.message(name, "Only the owner of this warpstone can set its destination.", true) + return + end + minetest.show_formspec(name, "warps:warpstone_diamond", warp_formspec(name)) + return + elseif node.name == "warps:warpstone_mese" then + if name ~= owner then + minetest.show_formspec(name, "warps:warpstone_mese_switch", + switch_class_fs(clicker)) + return + end + local codex = minetest.deserialize(meta:get_string("codex")) + local formspec = "size[8,3.5]" .. + jas0.exit_button() .. + jas0.help_button() .. + "button_exit[1.8,2.65;2,1;save;Save]" .. + "button_exit[4.7,2.65;2,1;switch;Switch]" .. + "" + for class, level in pairs(codex) do + local xp = tostring(level):gsub("(.*)%.", "") + formspec = formspec .. + "label[0,0;Saved Stats]" .. + "label[0.34,0.5;Class: " .. class .. "]" .. + "label[0.34,1;Level: " .. tostring(level):gsub("%.(.*)", "") .. "]" .. + "label[0.34,1.5;XP: " .. xp:sub(1, 2) .. "]" .. + "" + end + minetest.show_formspec(name, "warps:warpstone_mese", formspec) + end +end + +local on_blast = function() +end + +local can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + if meta:get_string("owner") ~= player:get_player_name() then + jas0.message(player, "Only the owner of this warpstone may break it.") + return false + else + return true + end +end + +after_dig_node = function(pos, oldnode, oldmetadata, digger) + if oldnode.name == "warps:warpstone_mese" then + local name = digger:get_player_name() + selected[name] = oldmetadata + jas0.message(digger, "Would you like to apply the stored class and level?", true, "warps:warpstone_mese_apply") + end +end + +local after_place_node = function(pos, placer, itemstack, pointed_thing) + local meta = minetest.get_meta(pos) + local name = placer:get_player_name() + if not name or not meta then + return + end + meta:set_string("owner", name) + if itemstack:get_name() == "warps:warpstone_mese" then + local p_meta = placer:get_meta() + local class = p_meta:get("class") + local level = jas0.level(placer) + meta:set_string("infotext", + "Mese Warpstone\nOwned by " .. name .. + "\n" .. class .. ": " .. tostring(level):gsub("%.(.*)", "")) + meta:set_string("codex", minetest.serialize({[class] = level})) + jas0.level(placer, -jas0.level(placer)) + jas0.message(name, "Your level and class have been preserved in the warpstone.\n" .. + "However, your level has been reset to 0.") + elseif itemstack:get_name() == "warps:warpstone_diamond" then + meta:set_string("infotext", "Uninitialized warpstone\n" .. + "Right-click to set destination.") + end +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + local name = player:get_player_name() + if formname == "warps:warpstone_diamond" then + local w = fields.warp + if w then + local b = beds.beds[name] + if b[w] then + local n = minetest.get_meta(selected[name]) + selected[name] = nil + if n then + n:set_string("warp", + minetest.serialize(b[w])) + n:set_string("destination", w) + n:set_string("infotext", "Warp to " .. w .. + "\nPunch and stand still to warp") + end + return + end + for name, warps in pairs(beds.beds_public) do + for warp, pos in pairs(warps) do + if w == warp then + local n = minetest.get_meta(selected[name]) + selected[name] = nil + if n then + n:set_string("warp", + minetest.serialize(pos)) + n:set_string("destination", w) + n:set_string("infotext", "Warp to " .. w .. + "\nPunch and stand still to warp") + end + return + end + end + end + end + end + if formname == "warps:warpstone_mese" then + if fields.save then + jas0.message(name, "The cost is one mese crystal.", + true, "warps:warpstone_mese_cost") + elseif fields.switch then + minetest.show_formspec(name, + "warps:warpstone_mese_switch", + switch_class_fs(player)) + elseif fields.help then + jas0.message(name, "Placing this node resets your class level." .. + " However, your class and level are preserved " .. + "in this warpstone. Digging it will restore them" .. + " after a dialog confirmation.\n\nIf this is not " .. + "your warpstone, then you can only switch your class" .. + " here. You cannot save, nor dig the warpstone.", + true, nil, "Mese Warpstone Help", true) + end + elseif formname == "warps:warpstone_mese_switch" and fields.switch then + jas0.change_class(player, string.lower(fields.class), true) + jas0.message(player, "Switched to " .. + string.lower(fields.class) .. " class.") + elseif formname == "warps:warpstone_mese_switch" and fields.help then + jas0.message(name, "Placing this node resets your class level." .. + " However, your class and level are preserved " .. + "in this warpstone. Digging it will restore them" .. + " after a dialog confirmation.\n\nIf this is not " .. + "your warpstone, then you can only switch your class" .. + " here. You cannot save, nor dig the warpstone.", + true, nil, "Mese Warpstone Help", true) + elseif formname == "warps:warpstone_mese_cost" and fields.ok then + local inv = player:get_inventory() + if inv:contains_item("main", "default:mese_crystal") then + inv:remove_item("main", "default:mese_crystal") + local name = player:get_player_name() + local meta = minetest.get_meta(selected[name]) + selected[name] = nil + local class = player:get_meta():get("class") + local level = jas0.level(player) + meta:set_string("codex", minetest.serialize({[class] = level})) + meta:set_string("infotext", "Mese Warpstone\nOwned by " .. name .. + "\n" .. class .. ": " .. tostring(level):gsub("%.(.*)", "")) + jas0.message(player, "Your class and level have been saved.", true) + else + jas0.message(player, "You do not have a mese crystal!", true) + end + elseif formname == "warps:warpstone_mese_apply" and fields.ok then + local name = player:get_player_name() + local codex = minetest.deserialize(selected[name].fields.codex) + selected[name] = nil + for k, v in pairs(codex) do + jas0.change_class(player, k) + local level = jas0.level(player) + if v < level then + return jas0.message(name, "That is a level lower than your current one.") + end + jas0.level(player, v - level) + end + end +end) + +minetest.register_on_leaveplayer(function(player) + if not player then + return + end + selected[player:get_player_name()] = nil +end) + +for label, color in pairs(warps) do + minetest.register_node("warps:warpgoo_" .. label, { + description = label .. " Warp Goo", + drawtype = "glasslike", + sounds = default.node_sound_water_defaults(), + paramtype = "light", + drop = "vessels:glass_fragments 3", -- TODO Use bucket instead. + tiles = {{ + name = "warps_warpgoo_" .. label .. ".png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }}, + post_effect_color = color, + sunlight_propagates = true, + walkable = false, + drowning = 3, + groups = {oddly_breakable_by_hand = 1}, + light_source = 13, + -- `alpha' and `use_texture_alpha' do not seem to have an effect, + -- but removing them results in an invisible node! + alpha = 191, + use_texture_alpha = true, + }) + minetest.register_node("warps:warpstone_" .. label, { + visual = "mesh", + mesh = "warps_warpstone.obj", + description = label .. " Warp Stone", + tiles = {"warps_" .. label .. "_warpstone.png"}, + drawtype = "mesh", + wield_scale = {x = 1.5, y = 1.5, z = 1.5}, + stack_max = 1, + sunlight_propagates = true, + walkable = false, + paramtype = "light", + paramtype2 = "facedir", + use_texture_alpha = true, + groups = {cracky = 3, oddly_breakable_by_hand = 1}, + light_source = 11, + sounds = default.node_sound_glass_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25} + }, + on_rightclick = on_rightclick, + on_blast = on_blast, + after_place_node = after_place_node, + can_dig = can_dig, + after_dig_node = after_dig_node, + on_punch = on_punch, + }) + local mat + if label ~= "mese" then + mat = label .. "block" + else + mat = label + end + minetest.register_craft({ + output = "warps:warpstone_" .. label, + recipe = { + {"group:glass", "group:glass", "group:glass"}, + {"group:glass", "default:" .. mat, "group:glass"}, + {"group:glass", "group:glass", "group:glass"} + } + }) +end diff --git a/mods/warps/mod.conf b/mods/warps/mod.conf new file mode 100644 index 0000000..26992a5 --- /dev/null +++ b/mods/warps/mod.conf @@ -0,0 +1 @@ +name = warps diff --git a/mods/warps/models/warps_warpstone.obj b/mods/warps/models/warps_warpstone.obj new file mode 100644 index 0000000..5858c88 --- /dev/null +++ b/mods/warps/models/warps_warpstone.obj @@ -0,0 +1,70 @@ +# Blender v2.60 (sub 0) OBJ File: '' +# www.blender.org +mtllib warps_warpstone.mtl +o Plane +v 0.000345 -0.332211 0.238072 +v -0.238873 -0.332211 -0.000181 +v -0.187467 0.347788 0.000753 +v 0.003339 0.347788 0.186987 +v -0.000061 0.473738 -0.000013 +v -0.000061 -0.400212 -0.000013 +v 0.238345 -0.332211 0.000071 +v 0.187345 0.347788 -0.000779 +v -0.000467 -0.332211 -0.238097 +v -0.003461 0.347788 -0.187013 +vt 0.247005 0.000534 +vt 0.000000 0.000534 +vt 0.000000 0.499516 +vt 0.247005 0.499516 +vt 0.744000 0.749758 +vt 0.744000 0.501019 +vt 0.248498 0.501019 +vt 0.248498 0.749758 +vt 0.495503 0.000534 +vt 0.248498 0.000534 +vt 0.248498 0.499516 +vt 0.495503 0.499516 +vt 0.744000 1.000000 +vt 0.744000 0.751261 +vt 0.248498 0.751261 +vt 0.248498 1.000000 +vt 0.247005 1.000000 +vt 0.247005 0.752012 +vt 0.000746 1.000000 +vt 0.497742 0.249273 +vt 0.744000 0.001285 +vt 0.744000 0.249273 +vt 0.744000 0.251528 +vt 0.497742 0.499516 +vt 0.744000 0.499516 +vt 0.247005 0.749758 +vt 0.000746 0.749758 +vt 0.247005 0.501770 +vt 0.000000 0.751261 +vt 0.000000 0.999249 +vt 0.246259 0.751261 +vt 0.743254 0.000534 +vt 0.496995 0.248522 +vt 0.496995 0.000534 +vt 0.496995 0.250776 +vt 0.496995 0.498764 +vt 0.743254 0.250776 +vt 0.000000 0.501019 +vt 0.246259 0.501019 +vt 0.000000 0.749006 +g Plane_Plane_Material.001 +usemtl Material.001 +s off +f 2/1 1/2 4/3 3/4 +f 1/5 7/6 8/7 4/8 +f 7/9 9/10 10/11 8/12 +f 9/13 2/14 3/15 10/16 +s 1 +f 5/17 3/18 4/19 +f 1/20 2/21 6/22 +f 7/23 1/24 6/25 +f 5/26 4/27 8/28 +f 5/29 8/30 10/31 +f 9/32 7/33 6/34 +f 6/35 2/36 9/37 +f 5/38 10/39 3/40 diff --git a/mods/warps/screenshot.png b/mods/warps/screenshot.png new file mode 100644 index 0000000..cae38f1 Binary files /dev/null and b/mods/warps/screenshot.png differ diff --git a/mods/warps/sounds/warps_woosh.ogg b/mods/warps/sounds/warps_woosh.ogg new file mode 100644 index 0000000..3649ca7 Binary files /dev/null and b/mods/warps/sounds/warps_woosh.ogg differ diff --git a/mods/warps/textures/warps_amethyst_warpstone.png b/mods/warps/textures/warps_amethyst_warpstone.png new file mode 100644 index 0000000..5b37ff3 Binary files /dev/null and b/mods/warps/textures/warps_amethyst_warpstone.png differ diff --git a/mods/warps/textures/warps_diamond_warpstone.png b/mods/warps/textures/warps_diamond_warpstone.png new file mode 100644 index 0000000..f30aff9 Binary files /dev/null and b/mods/warps/textures/warps_diamond_warpstone.png differ diff --git a/mods/warps/textures/warps_emerald_warpstone.png b/mods/warps/textures/warps_emerald_warpstone.png new file mode 100644 index 0000000..70a3d9e Binary files /dev/null and b/mods/warps/textures/warps_emerald_warpstone.png differ diff --git a/mods/warps/textures/warps_mese_warpstone.png b/mods/warps/textures/warps_mese_warpstone.png new file mode 100644 index 0000000..0407439 Binary files /dev/null and b/mods/warps/textures/warps_mese_warpstone.png differ diff --git a/mods/warps/textures/warps_ruby_warpstone.png b/mods/warps/textures/warps_ruby_warpstone.png new file mode 100644 index 0000000..33c1f4e Binary files /dev/null and b/mods/warps/textures/warps_ruby_warpstone.png differ diff --git a/mods/warps/textures/warps_warpgoo_amethyst.png b/mods/warps/textures/warps_warpgoo_amethyst.png new file mode 100644 index 0000000..79653a6 Binary files /dev/null and b/mods/warps/textures/warps_warpgoo_amethyst.png differ diff --git a/mods/warps/textures/warps_warpgoo_diamond.png b/mods/warps/textures/warps_warpgoo_diamond.png new file mode 100644 index 0000000..79653a6 Binary files /dev/null and b/mods/warps/textures/warps_warpgoo_diamond.png differ diff --git a/mods/warps/textures/warps_warpgoo_mese.png b/mods/warps/textures/warps_warpgoo_mese.png new file mode 100644 index 0000000..79653a6 Binary files /dev/null and b/mods/warps/textures/warps_warpgoo_mese.png differ diff --git a/mods/wieldview/LICENSE.txt b/mods/wieldview/LICENSE.txt new file mode 100644 index 0000000..4e8d524 --- /dev/null +++ b/mods/wieldview/LICENSE.txt @@ -0,0 +1,5 @@ +[mod] visible wielded items [wieldview] +======================================= + +License Source Code: Copyright (C) 2013-2017 Stuart Jones - LGPL v2.1 + diff --git a/mods/wieldview/README.txt b/mods/wieldview/README.txt new file mode 100644 index 0000000..ffa5ef0 --- /dev/null +++ b/mods/wieldview/README.txt @@ -0,0 +1,23 @@ +[mod] visible wielded items [wieldview] +======================================= + +Depends on: 3d_armor + +Makes hand wielded items visible to other players. + +default settings: [minetest.conf] + +# Set number of seconds between visible wielded item updates. +wieldview_update_time = 2 + +# Show nodes as tiles, disabled by default +wieldview_node_tiles = false + + +Info for modders +################ + +Wield image transformation: To apply a simple transformation to the item in +hand, add the group “wieldview_transform” to the item definition. The group +rating equals one of the numbers used for the [transform texture modifier +of the Lua API. diff --git a/mods/wieldview/depends.txt b/mods/wieldview/depends.txt new file mode 100644 index 0000000..b6cac21 --- /dev/null +++ b/mods/wieldview/depends.txt @@ -0,0 +1 @@ +3d_armor diff --git a/mods/wieldview/description.txt b/mods/wieldview/description.txt new file mode 100644 index 0000000..0d51ad9 --- /dev/null +++ b/mods/wieldview/description.txt @@ -0,0 +1 @@ +Makes hand wielded items visible to other players. diff --git a/mods/wieldview/init.lua b/mods/wieldview/init.lua new file mode 100644 index 0000000..5928678 --- /dev/null +++ b/mods/wieldview/init.lua @@ -0,0 +1,83 @@ +local time = 0 +local update_time = tonumber(minetest.settings:get("wieldview_update_time")) +if not update_time then + update_time = 2 + minetest.settings:set("wieldview_update_time", tostring(update_time)) +end +local node_tiles = minetest.settings:get_bool("wieldview_node_tiles") +if not node_tiles then + node_tiles = false + minetest.settings:set("wieldview_node_tiles", "false") +end + +wieldview = { + wielded_item = {}, + transform = {}, +} + +dofile(minetest.get_modpath(minetest.get_current_modname()).."/transform.lua") + +wieldview.get_item_texture = function(self, item) + local texture = "3d_armor_trans.png" + if item ~= "" then + if minetest.registered_items[item] then + if minetest.registered_items[item].inventory_image ~= "" then + texture = minetest.registered_items[item].inventory_image + elseif node_tiles == true and minetest.registered_items[item].tiles + and type(minetest.registered_items[item].tiles[1]) == "string" + and minetest.registered_items[item].tiles[1] ~= "" then + texture = minetest.inventorycube(minetest.registered_items[item].tiles[1]) + end + end + -- Get item image transformation, first from group, then from transform.lua + local transform = minetest.get_item_group(item, "wieldview_transform") + if transform == 0 then + transform = wieldview.transform[item] + end + if transform then + -- This actually works with groups ratings because transform1, transform2, etc. + -- have meaning and transform0 is used for identidy, so it can be ignored + texture = texture.."^[transform"..tostring(transform) + end + end + return texture +end + +wieldview.update_wielded_item = function(self, player) + if not player then + return + end + local name = player:get_player_name() + local stack = player:get_wielded_item() + local item = stack:get_name() + if not item then + return + end + if self.wielded_item[name] then + if self.wielded_item[name] == item then + return + end + armor.textures[name].wielditem = self:get_item_texture(item) + armor:update_player_visuals(player) + end + self.wielded_item[name] = item +end + +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + wieldview.wielded_item[name] = "" + minetest.after(1, function(player) + wieldview:update_wielded_item(player) + end, player) +end) + +minetest.register_globalstep(function(dtime) + time = time + dtime + if time > update_time then + for _,player in ipairs(minetest.get_connected_players()) do + wieldview:update_wielded_item(player) + end + time = 0 + end +end) + diff --git a/mods/wieldview/transform.lua b/mods/wieldview/transform.lua new file mode 100644 index 0000000..4d5133e --- /dev/null +++ b/mods/wieldview/transform.lua @@ -0,0 +1,24 @@ +-- Wielded Item Transformations - http://dev.minetest.net/texture + +wieldview.transform = { + ["default:torch"]="R270", + ["default:sapling"]="R270", + ["flowers:dandelion_white"]="R270", + ["flowers:dandelion_yellow"]="R270", + ["flowers:geranium"]="R270", + ["flowers:rose"]="R270", + ["flowers:tulip"]="R270", + ["flowers:viola"]="R270", + ["bucket:bucket_empty"]="R270", + ["bucket:bucket_water"]="R270", + ["bucket:bucket_lava"]="R270", + ["screwdriver:screwdriver"]="R270", + ["screwdriver:screwdriver1"]="R270", + ["screwdriver:screwdriver2"]="R270", + ["screwdriver:screwdriver3"]="R270", + ["screwdriver:screwdriver4"]="R270", + ["vessels:glass_bottle"]="R270", + ["vessels:drinking_glass"]="R270", + ["vessels:steel_bottle"]="R270", +} + diff --git a/mods/wool/README.txt b/mods/wool/README.txt new file mode 100644 index 0000000..a66677d --- /dev/null +++ b/mods/wool/README.txt @@ -0,0 +1,16 @@ +Minetest Game mod: wool +======================= +See license.txt for license information. + +Authors of source code +---------------------- +Originally by Perttu Ahola (celeron55) (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +Cisoun (CC BY-SA 3.0): + wool_black.png wool_brown.png wool_dark_green.png wool_green.png + wool_magenta.png wool_pink.png wool_violet.png wool_yellow.png + wool_blue.png wool_cyan.png wool_dark_grey.png wool_grey.png + wool_orange.png wool_red.png wool_white.png diff --git a/mods/wool/depends.txt b/mods/wool/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/wool/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/wool/init.lua b/mods/wool/init.lua new file mode 100644 index 0000000..3e565a4 --- /dev/null +++ b/mods/wool/init.lua @@ -0,0 +1,41 @@ +local dyes = { + {"white", "White"}, + {"grey", "Grey"}, + {"black", "Black"}, + {"red", "Red"}, + {"yellow", "Yellow"}, + {"green", "Green"}, + {"cyan", "Cyan"}, + {"blue", "Blue"}, + {"magenta", "Magenta"}, + {"orange", "Orange"}, + {"violet", "Violet"}, + {"brown", "Brown"}, + {"pink", "Pink"}, + {"dark_grey", "Dark Grey"}, + {"dark_green", "Dark Green"}, +} + +for i = 1, #dyes do + local name, desc = unpack(dyes[i]) + + minetest.register_node("wool:" .. name, { + description = desc .. " Wool", + tiles = {"wool_" .. name .. ".png"}, + is_ground_content = false, + groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, + flammable = 3, wool = 1}, + sounds = default.node_sound_defaults(), + }) + + minetest.register_craft{ + type = "shapeless", + output = "wool:" .. name, + recipe = {"group:dye,color_" .. name, "group:wool"}, + } +end + +-- Legacy +-- Backwards compatibility with jordach's 16-color wool mod +minetest.register_alias("wool:dark_blue", "wool:blue") +minetest.register_alias("wool:gold", "wool:yellow") diff --git a/mods/wool/license.txt b/mods/wool/license.txt new file mode 100644 index 0000000..9310163 --- /dev/null +++ b/mods/wool/license.txt @@ -0,0 +1,60 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 Perttu Ahola (celeron55) +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2012-2016 Cisoun + +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/wool/textures/wool_black.png b/mods/wool/textures/wool_black.png new file mode 100644 index 0000000..700d439 Binary files /dev/null and b/mods/wool/textures/wool_black.png differ diff --git a/mods/wool/textures/wool_blue.png b/mods/wool/textures/wool_blue.png new file mode 100644 index 0000000..a074986 Binary files /dev/null and b/mods/wool/textures/wool_blue.png differ diff --git a/mods/wool/textures/wool_brown.png b/mods/wool/textures/wool_brown.png new file mode 100644 index 0000000..2620dfd Binary files /dev/null and b/mods/wool/textures/wool_brown.png differ diff --git a/mods/wool/textures/wool_cyan.png b/mods/wool/textures/wool_cyan.png new file mode 100644 index 0000000..395b6ac Binary files /dev/null and b/mods/wool/textures/wool_cyan.png differ diff --git a/mods/wool/textures/wool_dark_green.png b/mods/wool/textures/wool_dark_green.png new file mode 100644 index 0000000..0e73999 Binary files /dev/null and b/mods/wool/textures/wool_dark_green.png differ diff --git a/mods/wool/textures/wool_dark_grey.png b/mods/wool/textures/wool_dark_grey.png new file mode 100644 index 0000000..7253696 Binary files /dev/null and b/mods/wool/textures/wool_dark_grey.png differ diff --git a/mods/wool/textures/wool_green.png b/mods/wool/textures/wool_green.png new file mode 100644 index 0000000..dcb663b Binary files /dev/null and b/mods/wool/textures/wool_green.png differ diff --git a/mods/wool/textures/wool_grey.png b/mods/wool/textures/wool_grey.png new file mode 100644 index 0000000..2f4c338 Binary files /dev/null and b/mods/wool/textures/wool_grey.png differ diff --git a/mods/wool/textures/wool_magenta.png b/mods/wool/textures/wool_magenta.png new file mode 100644 index 0000000..5c2c4a7 Binary files /dev/null and b/mods/wool/textures/wool_magenta.png differ diff --git a/mods/wool/textures/wool_orange.png b/mods/wool/textures/wool_orange.png new file mode 100644 index 0000000..a059f36 Binary files /dev/null and b/mods/wool/textures/wool_orange.png differ diff --git a/mods/wool/textures/wool_pink.png b/mods/wool/textures/wool_pink.png new file mode 100644 index 0000000..8e90140 Binary files /dev/null and b/mods/wool/textures/wool_pink.png differ diff --git a/mods/wool/textures/wool_red.png b/mods/wool/textures/wool_red.png new file mode 100644 index 0000000..da12ecf Binary files /dev/null and b/mods/wool/textures/wool_red.png differ diff --git a/mods/wool/textures/wool_violet.png b/mods/wool/textures/wool_violet.png new file mode 100644 index 0000000..d7d6783 Binary files /dev/null and b/mods/wool/textures/wool_violet.png differ diff --git a/mods/wool/textures/wool_white.png b/mods/wool/textures/wool_white.png new file mode 100644 index 0000000..88f1e2f Binary files /dev/null and b/mods/wool/textures/wool_white.png differ diff --git a/mods/wool/textures/wool_yellow.png b/mods/wool/textures/wool_yellow.png new file mode 100644 index 0000000..2b0f048 Binary files /dev/null and b/mods/wool/textures/wool_yellow.png differ diff --git a/mods/xpanes/README.txt b/mods/xpanes/README.txt new file mode 100644 index 0000000..47161da --- /dev/null +++ b/mods/xpanes/README.txt @@ -0,0 +1,24 @@ +Minetest Game mod: xpanes +========================= +See license.txt for license information. + +Authors of source code +---------------------- +Originally by xyz (MIT) +BlockMen (MIT) +sofar (MIT) +Various Minetest developers and contributors (MIT) + +Authors of media (textures) +--------------------------- +xyz (CC BY-SA 3.0): + All textures not mentioned below. + +Gambit (CC BY-SA 3.0): + xpanes_bar.png + +paramat (CC BY-SA 3.0): + xpanes_bar_top.png + +Krock (CC0 1.0): + xpanes_edge.png diff --git a/mods/xpanes/depends.txt b/mods/xpanes/depends.txt new file mode 100644 index 0000000..9e72f07 --- /dev/null +++ b/mods/xpanes/depends.txt @@ -0,0 +1,2 @@ +default +backpacks diff --git a/mods/xpanes/init.lua b/mods/xpanes/init.lua new file mode 100644 index 0000000..01eba90 --- /dev/null +++ b/mods/xpanes/init.lua @@ -0,0 +1,249 @@ + +local function is_pane(pos) + return minetest.get_item_group(minetest.get_node(pos).name, "pane") > 0 +end + +local function connects_dir(pos, name, dir) + local aside = vector.add(pos, minetest.facedir_to_dir(dir)) + if is_pane(aside) then + return true + end + + local connects_to = minetest.registered_nodes[name].connects_to + if not connects_to then + return false + end + local list = minetest.find_nodes_in_area(aside, aside, connects_to) + + if #list > 0 then + return true + end + + return false +end + +local function swap(pos, node, name, param2) + if node.name == name and node.param2 == param2 then + return + end + + minetest.set_node(pos, {name = name, param2 = param2}) +end + +local function update_pane(pos) + if not is_pane(pos) then + return + end + local node = minetest.get_node(pos) + local name = node.name + if name:sub(-5) == "_flat" then + name = name:sub(1, -6) + end + + local any = node.param2 + local c = {} + local count = 0 + for dir = 0, 3 do + c[dir] = connects_dir(pos, name, dir) + if c[dir] then + any = dir + count = count + 1 + end + end + + if count == 0 then + swap(pos, node, name .. "_flat", any) + elseif count == 1 then + swap(pos, node, name .. "_flat", (any + 1) % 4) + elseif count == 2 then + if (c[0] and c[2]) or (c[1] and c[3]) then + swap(pos, node, name .. "_flat", (any + 1) % 4) + else + swap(pos, node, name, 0) + end + else + swap(pos, node, name, 0) + end +end +local nodes_scout_can_place = { + "default:torch", + "backpacks:backpack_leather", +} +for i = 1, #nodes_scout_can_place do + if not minetest.registered_nodes[nodes_scout_can_place[i]].groups then + break + end + local groups = minetest.registered_nodes[nodes_scout_can_place[i]].groups + groups.scout_can_place = 1 + minetest.override_item(nodes_scout_can_place[i], { + groups = groups, + }) +end +minetest.register_on_placenode(function(pos, node, placer, oldnode, itemstack, pointed_thing) + -- What in the world is minetest.registered_on_placenodes? + local class = placer:get_meta():get("class") + if placer and class == "scout" then + if minetest.get_item_group(node.name, "scout_can_place") > 0 then + return true + end + minetest.add_item(pos, node) + minetest.set_node(pos, {name = "air"}) + return false + end + -- This is always true? + if minetest.get_item_group(node, "pane") then + update_pane(pos) + end + for i = 0, 3 do + local dir = minetest.facedir_to_dir(i) + update_pane(vector.add(pos, dir)) + end +end) + +minetest.register_on_dignode(function(pos) + for i = 0, 3 do + local dir = minetest.facedir_to_dir(i) + update_pane(vector.add(pos, dir)) + end +end) + +xpanes = {} +function xpanes.register_pane(name, def) + for i = 1, 15 do + minetest.register_alias("xpanes:" .. name .. "_" .. i, "xpanes:" .. name .. "_flat") + end + + local flatgroups = table.copy(def.groups) + flatgroups.pane = 1 + minetest.register_node(":xpanes:" .. name .. "_flat", { + description = def.description, + drawtype = "nodebox", + paramtype = "light", + is_ground_content = false, + sunlight_propagates = true, + inventory_image = def.inventory_image, + wield_image = def.wield_image, + paramtype2 = "facedir", + tiles = {def.textures[3], def.textures[3], def.textures[1]}, + groups = flatgroups, + drop = "xpanes:" .. name .. "_flat", + sounds = def.sounds, + use_texture_alpha = def.use_texture_alpha or false, + node_box = { + type = "fixed", + fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}}, + }, + selection_box = { + type = "fixed", + fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}}, + }, + connect_sides = { "left", "right" }, + }) + + local groups = table.copy(def.groups) + groups.pane = 1 + groups.not_in_creative_inventory = 1 + minetest.register_node(":xpanes:" .. name, { + drawtype = "nodebox", + paramtype = "light", + is_ground_content = false, + sunlight_propagates = true, + description = def.description, + tiles = {def.textures[3], def.textures[3], def.textures[1]}, + groups = groups, + drop = "xpanes:" .. name .. "_flat", + sounds = def.sounds, + use_texture_alpha = def.use_texture_alpha or false, + node_box = { + type = "connected", + fixed = {{-1/32, -1/2, -1/32, 1/32, 1/2, 1/32}}, + connect_front = {{-1/32, -1/2, -1/2, 1/32, 1/2, -1/32}}, + connect_left = {{-1/2, -1/2, -1/32, -1/32, 1/2, 1/32}}, + connect_back = {{-1/32, -1/2, 1/32, 1/32, 1/2, 1/2}}, + connect_right = {{1/32, -1/2, -1/32, 1/2, 1/2, 1/32}}, + }, + connects_to = {"group:pane", "group:stone", "group:glass", "group:wood", "group:tree"}, + }) + + minetest.register_craft({ + output = "xpanes:" .. name .. "_flat 8", + recipe = def.recipe + }) +end + +for k, v in ipairs(dye.dyes) do + if v[1] == "white" then + xpanes.register_pane("pane", { + description = "Glass Pane", + textures = { + "default_glass.png", + "xpanes_pane_half.png", + "xpanes_edge.png" + }, + inventory_image = "default_glass.png", + wield_image = "default_glass.png", + sounds = default.node_sound_glass_defaults(), + groups = {snappy = 2, cracky = 3, oddly_breakable_by_hand = 3}, + recipe = { + {"default:glass", "default:glass", "default:glass"}, + {"default:glass", "default:glass", "default:glass"} + } + }) + else + local c = v[1]:gsub("_", "") + xpanes.register_pane("pane_" .. v[1], { + description = v[2] .. " Glass Pane", + textures = { + "default_glass.png^[colorize:" .. c, + "xpanes_pane_half.png^[colorize:" .. c, + "xpanes_edge.png^[colorize:" .. c, + }, + inventory_image = "default_glass.png^[colorize:" .. c, + wield_image = "default_glass.png^[colorize:" .. c, + sounds = default.node_sound_glass_defaults(), + groups = {snappy = 2, cracky = 3, oddly_breakable_by_hand = 3}, + recipe = { + {"dye:" .. v[1], "dye:" .. v[1], "dye:" .. v[1]}, + {"default:glass", "default:glass", "default:glass"}, + {"default:glass", "default:glass", "default:glass"} + } + }) + end +end +xpanes.register_pane("obsidian_pane", { + description = "Obsidian Glass Pane", + textures = {"default_obsidian_glass.png","xpanes_pane_half.png","xpanes_edge_obsidian.png"}, + inventory_image = "default_obsidian_glass.png", + wield_image = "default_obsidian_glass.png", + sounds = default.node_sound_glass_defaults(), + groups = {snappy=2, cracky=3}, + recipe = { + {"default:obsidian_glass", "default:obsidian_glass", "default:obsidian_glass"}, + {"default:obsidian_glass", "default:obsidian_glass", "default:obsidian_glass"} + } +}) + +xpanes.register_pane("bar", { + description = "Steel Bars", + textures = {"xpanes_bar.png","xpanes_bar.png","xpanes_bar_top.png"}, + inventory_image = "xpanes_bar.png", + wield_image = "xpanes_bar.png", + groups = {cracky=2}, + sounds = default.node_sound_metal_defaults(), + recipe = { + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"}, + {"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"} + } +}) + +minetest.register_lbm({ + name = "xpanes:gen2", + nodenames = {"group:pane"}, + action = function(pos, node) + update_pane(pos) + for i = 0, 3 do + local dir = minetest.facedir_to_dir(i) + update_pane(vector.add(pos, dir)) + end + end +}) diff --git a/mods/xpanes/license.txt b/mods/xpanes/license.txt new file mode 100644 index 0000000..dff7227 --- /dev/null +++ b/mods/xpanes/license.txt @@ -0,0 +1,64 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2014-2016 xyz +Copyright (C) 2014-2016 BlockMen +Copyright (C) 2016 Auke Kok +Copyright (C) 2014-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + + +Licenses of media (textures) +---------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2014-2016 xyz +Copyright (C) 2013-2016 Gambit +Copyright (C) 2016 paramat + +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/xpanes/textures/xpanes_bar.png b/mods/xpanes/textures/xpanes_bar.png new file mode 100644 index 0000000..3ea62a9 Binary files /dev/null and b/mods/xpanes/textures/xpanes_bar.png differ diff --git a/mods/xpanes/textures/xpanes_bar_top.png b/mods/xpanes/textures/xpanes_bar_top.png new file mode 100644 index 0000000..7b74508 Binary files /dev/null and b/mods/xpanes/textures/xpanes_bar_top.png differ diff --git a/mods/xpanes/textures/xpanes_edge.png b/mods/xpanes/textures/xpanes_edge.png new file mode 100644 index 0000000..5768d66 Binary files /dev/null and b/mods/xpanes/textures/xpanes_edge.png differ diff --git a/mods/xpanes/textures/xpanes_edge_obsidian.png b/mods/xpanes/textures/xpanes_edge_obsidian.png new file mode 100644 index 0000000..abdd14e Binary files /dev/null and b/mods/xpanes/textures/xpanes_edge_obsidian.png differ diff --git a/mods/xpanes/textures/xpanes_pane_half.png b/mods/xpanes/textures/xpanes_pane_half.png new file mode 100644 index 0000000..4e846df Binary files /dev/null and b/mods/xpanes/textures/xpanes_pane_half.png differ diff --git a/mods/xpanes/textures/xpanes_space.png b/mods/xpanes/textures/xpanes_space.png new file mode 100644 index 0000000..331e365 Binary files /dev/null and b/mods/xpanes/textures/xpanes_space.png differ diff --git a/mods/ydecor/depends.txt b/mods/ydecor/depends.txt new file mode 100644 index 0000000..cf9c693 --- /dev/null +++ b/mods/ydecor/depends.txt @@ -0,0 +1,2 @@ +stairs +default diff --git a/mods/ydecor/init.lua b/mods/ydecor/init.lua new file mode 100644 index 0000000..bfd9d13 --- /dev/null +++ b/mods/ydecor/init.lua @@ -0,0 +1,198 @@ +-- Coal Stone Tile +minetest.register_node("ydecor:coalstone_tile", { + description = "Coal Stone Tile", + tiles = {"ydecor_coalstone_tile.png"}, + groups = {cracky = 1, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) +minetest.register_craft({ + output = "ydecor:coalstone_tile 8", + recipe = { + {"default:coalblock", "default:stone"}, + {"default:stone", "default:coalblock"}, + } +}) +stairs.register_stair_and_slab("coalstone", "ydecor:coalstone_tile", + {cracky = 1, stone = 1}, {"ydecor_coalstone_tile.png"}, + "Coal Stone Stair", "Coal Stone Slab", + default.node_sound_stone_defaults(), + false) + +-- Moon Brick +minetest.register_node("ydecor:moonbrick", { + description = "Moon Brick", + tiles = {"ydecor_moonbrick.png"}, + groups = {cracky = 1}, + sounds = default.node_sound_stone_defaults(), +}) +minetest.register_craft({ + output = "ydecor:moonbrick", + recipe = { + {"default:brick", "default:stone"}, + } +}) +stairs.register_stair_and_slab("moonbrick", "ydecor:moonbrick", + {cracky = 1}, {"ydecor_moonbrick.png"}, + "Moon Brick Stair", "Moon Brick Slab", + default.node_sound_stone_defaults(), + false) + +-- Runestone +minetest.register_node("ydecor:stone_rune", { + description = "Runestone", + tiles = {"ydecor_stone_rune.png"}, + groups = {cracky = 1, stone = 1}, + sounds = default.node_sound_stone_defaults(), +}) +minetest.register_craft({ + output = "ydecor:stone_rune 8", + recipe = { + {"default:stone", "default:stone", "default:stone"}, + {"default:stone", "", "default:stone"}, + {"default:stone", "default:stone", "default:stone"}, + }, +}) +stairs.register_stair_and_slab("stone_rune", "ydecor:stone_rune", + {cracky = 1, stone = 1}, {"ydecor_stone_rune.png"}, + "Runestone Stair", "Runestone Slab", + default.node_sound_stone_defaults(), + false) + +-- Hardened Clay +minetest.register_node("ydecor:hard_clay", { + description = "Hardened Clay", + tiles = {"ydecor_hard_clay.png"}, + groups = {cracky = 1}, + sounds = default.node_sound_stone_defaults(), +}) +minetest.register_craft({ + output = "ydecor:hard_clay", + recipe = { + {"default:clay", "default:clay"}, + {"default:clay", "default:clay"} + } +}) +stairs.register_stair_and_slab("hard_clay", "ydecor:hard_clay", + {cracky = 1}, {"ydecor_hard_clay.png"}, + "Hard Clay Stair", "Hard Clay Slab", + default.node_sound_stone_defaults(), + false) + +-- Packed Ice +minetest.register_node("ydecor:packed_ice", { + description = "Packed Ice", + tiles = {"ydecor_packed_ice.png"}, + groups = {cracky = 1, slippery = 3}, + sounds = default.node_sound_glass_defaults(), +}) +minetest.register_craft({ + output = "ydecor:packed_ice", + recipe = { + {"default:ice", "default:ice"}, + {"default:ice", "default:ice"} + } +}) +stairs.register_stair_and_slab("packed_ice", "ydecor:packed_ice", + {cracky = 1, slippery = 3}, {"ydecor_packed_ice.png"}, + "Packed Ice Stair", "Packed Ice Slab", + default.node_sound_stone_defaults(), + false) + +-- Wooden Tile +minetest.register_node("ydecor:wood_tile", { + description = "Wooden Tile", + tiles = {"ydecor_wood_tile.png"}, + groups = {choppy = 1, wood = 1, flammable = 2}, + sounds = default.node_sound_wood_defaults(), +}) +minetest.register_craft({ + output = "ydecor:wood_tile 2", + recipe = { + {"", "group:wood", ""}, + {"group:wood", "", "group:wood"}, + {"", "group:wood", ""} + } +}) +stairs.register_stair_and_slab("wood_tile", "ydecor:wood_tile", + {choppy = 1, wood = 1, flammable = 2}, {"ydecor_wood_tile.png"}, + "Wooden Tile Stair", "Wooden Tile Slab", + default.node_sound_stone_defaults(), + false) + +-- Cobweb +minetest.register_node("ydecor:cobweb", { + description = "Cobweb", + drawtype = "plantlike", + tiles = {"ydecor_cobweb.png"}, + inventory_image = "ydecor_cobweb.png", + liquid_viscosity = 8, + liquidtype = "source", + liquid_alternative_flowing = "ydecor:cobweb", + liquid_alternative_source = "ydecor:cobweb", + liquid_renewable = false, + liquid_range = 0, + walkable = false, + selection_box = {type = "regular"}, + groups = {snappy = 3, liquid = 3, flammable = 3}, + sounds = default.node_sound_leaves_defaults(), + paramtype = "light", + sunlight_propagates = true, +}) + +minetest.register_craft({ + output = "ydecor:cobweb", + recipe = { + {"farming:string", "", "farming:string"}, + {"", "farming:string", ""}, + {"farming:string", "", "farming:string"} + } +}) + +-- Baricade +minetest.register_node("ydecor:baricade", { + description = "Baricade", + drawtype = "plantlike", + paramtype = "light", + paramtype2 = "facedir", + inventory_image = "ydecor_baricade.png", + tiles = {"ydecor_baricade.png"}, + groups = {choppy = 2, oddly_breakable_by_hand = 1, flammable = 2}, + damage_per_second = 4, + selection_box = {type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0.1, 0.3}}, + collision_box = {type = "fixed", fixed = {-0.1, -0.5, -0.1, 0.1, 0.1, 0.1}}, + sunlight_propagates = true, +}) + +minetest.register_craft({ + output = "ydecor:baricade", + recipe = { + {"group:stick", "", "group:stick"}, + {"", "default:steel_ingot", ""}, + {"group:stick", "", "group:stick"} + } +}) + +-- Ivy +minetest.register_node("ydecor:ivy", { + description = "Ivy", + drawtype = "signlike", + walkable = false, + climbable = true, + groups = {snappy = 3, flora = 1, attached_node = 1, plant = 1, flammable = 3}, + paramtype = "light", + paramtype2 = "wallmounted", + selection_box = {type = "wallmounted"}, + tiles = {"ydecor_ivy.png"}, + inventory_image = "ydecor_ivy.png", + wield_image = "ydecor_ivy.png", + sounds = default.node_sound_leaves_defaults(), + sunlight_propagates = true, +}) + +minetest.register_craft({ + output = "ydecor:ivy 2", + recipe = { + {"group:leaves"}, + {"group:leaves"} + } +}) diff --git a/mods/ydecor/textures/ydecor_baricade.png b/mods/ydecor/textures/ydecor_baricade.png new file mode 100644 index 0000000..87109bb Binary files /dev/null and b/mods/ydecor/textures/ydecor_baricade.png differ diff --git a/mods/ydecor/textures/ydecor_coalstone_tile.png b/mods/ydecor/textures/ydecor_coalstone_tile.png new file mode 100644 index 0000000..3122db0 Binary files /dev/null and b/mods/ydecor/textures/ydecor_coalstone_tile.png differ diff --git a/mods/ydecor/textures/ydecor_cobweb.png b/mods/ydecor/textures/ydecor_cobweb.png new file mode 100644 index 0000000..bb1ecea Binary files /dev/null and b/mods/ydecor/textures/ydecor_cobweb.png differ diff --git a/mods/ydecor/textures/ydecor_hard_clay.png b/mods/ydecor/textures/ydecor_hard_clay.png new file mode 100644 index 0000000..8abe666 Binary files /dev/null and b/mods/ydecor/textures/ydecor_hard_clay.png differ diff --git a/mods/ydecor/textures/ydecor_ivy.png b/mods/ydecor/textures/ydecor_ivy.png new file mode 100644 index 0000000..b85e112 Binary files /dev/null and b/mods/ydecor/textures/ydecor_ivy.png differ diff --git a/mods/ydecor/textures/ydecor_moonbrick.png b/mods/ydecor/textures/ydecor_moonbrick.png new file mode 100644 index 0000000..efdac14 Binary files /dev/null and b/mods/ydecor/textures/ydecor_moonbrick.png differ diff --git a/mods/ydecor/textures/ydecor_packed_ice.png b/mods/ydecor/textures/ydecor_packed_ice.png new file mode 100644 index 0000000..8c44eaf Binary files /dev/null and b/mods/ydecor/textures/ydecor_packed_ice.png differ diff --git a/mods/ydecor/textures/ydecor_stone_rune.png b/mods/ydecor/textures/ydecor_stone_rune.png new file mode 100644 index 0000000..319a2df Binary files /dev/null and b/mods/ydecor/textures/ydecor_stone_rune.png differ diff --git a/mods/ydecor/textures/ydecor_wood_tile.png b/mods/ydecor/textures/ydecor_wood_tile.png new file mode 100644 index 0000000..272df2c Binary files /dev/null and b/mods/ydecor/textures/ydecor_wood_tile.png differ diff --git a/mtg.LICENSE b/mtg.LICENSE new file mode 100644 index 0000000..48f0b8d --- /dev/null +++ b/mtg.LICENSE @@ -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/mtg.README b/mtg.README new file mode 100644 index 0000000..1af9e55 --- /dev/null +++ b/mtg.README @@ -0,0 +1,28 @@ +Minetest Game [minetest_game] +============================= +The main game for the Minetest engine +===================================== + +To use this game with the Minetest engine, insert this repository as + /games/minetest_game + +The Minetest engine can be found in: + https://github.com/minetest/minetest/ + +Compatibility +-------------- +The Minetest Game github master HEAD is generally compatible with the github +master HEAD of the Minetest engine. + +Additionally, when the Minetest engine is tagged to be a certain version (eg. +0.4.10), Minetest Game is tagged with the version too. + +When stable releases are made, Minetest Game is packaged and made available in + http://minetest.net/downloads/ +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!) + +Licensing +--------- + +See LICENSE.txt [Moved to mtg.LICENSE -jas 20181123] diff --git a/schematic_tables.txt b/schematic_tables.txt new file mode 100644 index 0000000..bd101e7 --- /dev/null +++ b/schematic_tables.txt @@ -0,0 +1,2176 @@ +Minetest Game schematic tables +============================== + +This document acts as the official record of all schematic tables used in +Minetest Game, and should be updated by any commit that adds a table type +schematic. + +The following tables are for pasting into mods that contain a function to +convert the Lua tables into .mts files. Such mods often have two functions to +process two formats of the 'data' table: + +The standard table format is described in the 'Schematic specifier' section of +the lua_api.txt file in the Minetest Engine. +The 'data' table appears as a sequence of vertical slices through the structure +the schematic describes. +Each XY-plane slice has the X-rows formatted in order of increasing Y, so the +slices of the structure visually appear upside-down in the table. +In this document this format is used where 'mts_save()' appears. + +The transformed table format was created to be easier to work with. +Each XY-plane slice has the X-rows formatted in order of decreasing Y, so the +slices of the structure visually appear upright in the table. +In this document this format is used where 'mts_save_up()' appears. + + +-- This node will not replace existing world nodes + +local _ = {name = "air", prob = 0} + + +-- Mapgen Apple tree + +local M = {name = "default:leaves", prob = 255} +local N = {name = "default:leaves", prob = 223} +local F = {name = "default:apple", prob = 63} +local Y = {name = "default:tree", prob = 255, force_place = true} +local T = {name = "default:tree", prob = 255} + +mts_save("apple_tree", { + size = {x = 7, y = 8, z = 7}, + data = { + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, M, N, _, _, + _, _, _, N, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, F, M, M, _, + _, N, M, M, M, N, _, + _, _, N, M, N, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, M, Y, _, _, M, N, + _, M, M, _, Y, M, _, + _, N, M, M, M, N, _, + _, _, _, N, _, _, _, + + _, _, _, Y, _, _, _, + _, _, _, Y, _, _, _, + _, _, _, Y, _, _, _, + _, _, _, Y, _, _, _, + M, F, _, Y, _, F, M, + N, M, _, _, _, M, N, + _, M, M, M, M, M, _, + _, _, N, M, N, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, M, _, _, Y, M, N, + _, M, Y, _, M, M, _, + _, N, M, M, M, N, _, + _, _, _, N, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, F, M, M, _, + _, N, M, M, M, N, _, + _, _, N, M, N, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, M, N, _, _, + _, _, _, N, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + }, +}) + + +-- Apple tree from sapling + +mts_save("apple_tree_from_sapling", { + size = {x = 7, y = 8, z = 7}, + data = { + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, M, N, _, _, + _, _, _, N, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, F, M, M, _, + _, N, M, M, M, N, _, + _, _, N, M, N, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, M, T, _, _, M, N, + _, M, M, _, T, M, _, + _, N, M, M, M, N, _, + _, _, _, N, _, _, _, + + _, _, _, T, _, _, _, + _, _, _, Y, _, _, _, + _, _, _, T, _, _, _, + _, _, _, T, _, _, _, + M, F, _, T, _, F, M, + N, M, _, _, _, M, N, + _, M, M, M, M, M, _, + _, _, N, M, N, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, M, _, _, T, M, N, + _, M, T, _, M, M, _, + _, N, M, M, M, N, _, + _, _, _, N, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, F, M, M, _, + _, N, M, M, M, N, _, + _, _, N, M, N, _, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, M, N, _, _, + _, _, _, N, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + }, +}) + + +-- Mapgen Jungle tree + +local L = {name = "default:jungleleaves", prob = 255} +local N = {name = "default:jungleleaves", prob = 223} +local M = {name = "default:jungleleaves", prob = 191} +local B = {name = "default:jungletree", prob = 255, force_place = true} +local Y = {name = "default:jungletree", prob = 191, force_place = true} +local U = {name = "default:jungletree", prob = 127, force_place = true} +local I = {name = "default:jungletree", prob = 255} + +mts_save("jungle_tree", { + size = {x = 5, y = 17, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, L, N, _, _, + _, _, N, L, N, + _, _, _, _, _, + _, _, _, _, _, + M, N, N, N, M, + M, N, N, N, M, + _, _, _, _, _, + + _, _, B, _, _, + _, _, B, _, _, + _, _, U, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, B, L, _, _, + _, _, L, B, L, + _, _, _, _, _, + _, _, _, _, _, + N, B, L, B, N, + N, L, L, L, N, + _, N, N, N, _, + + _, B, B, B, _, + _, B, B, B, _, + _, U, B, U, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, L, N, + N, L, B, _, _, + N, L, B, _, _, + _, _, B, L, N, + _, _, B, L, N, + _, _, B, _, _, + N, L, L, L, N, + N, L, L, L, N, + _, N, L, N, _, + + _, _, B, _, _, + _, _, B, _, _, + _, _, U, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, L, B, L, + L, B, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, L, B, L, + _, _, _, _, _, + N, B, L, B, N, + N, L, L, L, N, + _, N, N, N, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, N, L, N, + N, L, N, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, N, L, N, + _, _, _, _, _, + M, N, N, N, M, + M, N, N, N, M, + _, _, _, _, _, + }, + yslice_prob = { + {ypos=6, prob=191}, + {ypos=7, prob=191}, + {ypos=8, prob=191}, + {ypos=9, prob=191}, + {ypos=10, prob=191}, + }, +}) + + +-- Jungle tree from sapling + +local B = {name = "default:jungletree", prob = 255} +local C = {name = "default:jungletree", prob = 255, force_place = true} +local Y = {name = "default:jungletree", prob = 191} +local U = {name = "default:jungletree", prob = 127} + +mts_save("jungle_tree_from_sapling", { + size = {x = 5, y = 17, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, L, N, _, _, + _, _, N, L, N, + _, _, _, _, _, + _, _, _, _, _, + M, N, N, N, M, + M, N, N, N, M, + _, _, _, _, _, + + _, _, B, _, _, + _, _, B, _, _, + _, _, U, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, B, L, _, _, + _, _, L, B, L, + _, _, _, _, _, + _, _, _, _, _, + N, B, L, B, N, + N, L, L, L, N, + _, N, N, N, _, + + _, B, B, B, _, + _, B, C, B, _, + _, U, B, U, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, L, N, + N, L, B, _, _, + N, L, B, _, _, + _, _, B, L, N, + _, _, B, L, N, + _, _, B, _, _, + N, L, L, L, N, + N, L, L, L, N, + _, N, L, N, _, + + _, _, B, _, _, + _, _, B, _, _, + _, _, U, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, L, B, L, + L, B, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, L, B, L, + _, _, _, _, _, + N, B, L, B, N, + N, L, L, L, N, + _, N, N, N, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, N, L, N, + N, L, N, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, N, L, N, + _, _, _, _, _, + M, N, N, N, M, + M, N, N, N, M, + _, _, _, _, _, + }, + yslice_prob = { + {ypos=6, prob=191}, + {ypos=7, prob=191}, + {ypos=8, prob=191}, + {ypos=9, prob=191}, + {ypos=10, prob=191}, + }, +}) + + +-- Mapgen Pine tree + +local L = {name = "default:pine_needles", prob = 255} +local M = {name = "default:pine_needles", prob = 223} +local N = {name = "default:pine_needles", prob = 191} +local T = {name = "default:pine_tree", prob = 255, force_place = true} +local B = {name = "default:pine_tree", prob = 255} + +mts_save("pine_tree", { + size = {x = 5, y = 16, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, L, L, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + {ypos = 5, prob = 127}, + {ypos = 9, prob = 127}, + {ypos = 12, prob = 127}, + }, +}) + + +-- Pine tree from sapling + +local T = {name = "default:pine_tree", prob = 255} +local U = {name = "default:pine_tree", prob = 255, force_place = true} + +mts_save("pine_tree_from_sapling", { + size = {x = 5, y = 16, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + + _, _, T, _, _, + _, _, U, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, L, L, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + {ypos = 5, prob = 127}, + {ypos = 9, prob = 127}, + {ypos = 12, prob = 127}, + }, +}) + + +-- Snowy pine tree from sapling + +local T = {name = "default:pine_tree", prob = 255} +local U = {name = "default:pine_tree", prob = 255, force_place = true} +local L = {name = "default:pine_needles", prob = 255} +local S = {name = "default:snow", prob = 255} + +mts_save("snowy_pine_tree_from_sapling", { + size = {x = 5, y = 16, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + L, L, L, L, L, + S, S, S, S, S, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + L, L, _, L, M, + S, L, L, L, _, + _, _, _, _, _, + _, L, _, L, L, + _, L, L, L, S, + _, S, S, S, _, + _, _, _, _, _, + + _, _, T, _, _, + _, _, U, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + _, L, T, L, _, + _, _, T, _, _, + L, _, T, _, L, + S, L, L, L, S, + _, S, L, S, _, + _, _, S, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + M, L, _, L, M, + _, L, L, L, _, + _, _, _, _, _, + L, L, _, L, L, + S, L, L, L, S, + _, S, S, S, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, L, + _, _, _, _, S, + _, _, _, _, _, + L, L, L, L, _, + S, S, S, S, _, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + {ypos = 8, prob = 127}, + {ypos = 11, prob = 127}, + }, +}) + + +-- Mapgen Acacia tree + +local L = {name = "default:acacia_leaves", prob = 255} +local M = {name = "default:acacia_leaves", prob = 223} +local T = {name = "default:acacia_tree", prob = 255, force_place = true} + +mts_save("acacia_tree", { + size = {x = 9, y = 9, z = 9}, + data = { + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, M, M, M, _, _, _, _, _, + _, _, _, _, M, M, M, M, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, L, L, M, _, _, _, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, T, _, _, _, _, _, _, + M, L, L, M, _, _, T, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, T, _, _, _, _, _, + _, _, _, _, _, T, _, _, _, + M, M, M, M, _, _, _, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, M, M, M, M, M, M, M, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, T, _, _, _, + _, _, _, T, _, _, _, _, _, + _, _, _, _, _, M, M, M, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, T, _, _, + _, _, T, _, _, M, L, L, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, M, L, L, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, M, M, M, M, + M, M, M, M, M, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + }, +}) + + +-- Acacia tree from sapling + +local T = {name = "default:acacia_tree", prob = 255} +local U = {name = "default:acacia_tree", prob = 255, force_place = true} + +mts_save("acacia_tree_from_sapling", { + size = {x = 9, y = 9, z = 9}, + data = { + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, M, M, M, _, _, _, _, _, + _, _, _, _, M, M, M, M, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, L, L, M, _, _, _, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, T, _, _, _, _, _, _, + M, L, L, M, _, _, T, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, T, _, _, _, _, _, + _, _, _, _, _, T, _, _, _, + M, M, M, M, _, _, _, _, _, + _, _, _, _, M, L, L, L, M, + + _, _, _, _, T, _, _, _, _, + _, _, _, _, U, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, T, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + M, M, M, M, M, M, M, M, M, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, T, _, _, _, + _, _, _, T, _, _, _, _, _, + _, _, _, _, _, M, M, M, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, T, _, _, + _, _, T, _, _, M, L, L, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, M, L, L, M, + M, L, L, L, M, _, _, _, _, + + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, _, _, _, _, + _, _, _, _, _, M, M, M, M, + M, M, M, M, M, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + }, +}) + + +-- Mapgen Aspen tree + +local T = {name = "default:aspen_tree", prob = 255, force_place = true} +local B = {name = "default:aspen_tree", prob = 255} +local L = {name = "default:aspen_leaves", prob = 255} +local M = {name = "default:aspen_leaves", prob = 223} +local N = {name = "default:aspen_leaves", prob = 127} + +mts_save("aspen_tree", { + size = {x = 5, y = 14, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + _, _, _, _, _, + + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, L, T, L, _, + L, L, T, L, L, + _, L, T, L, _, + L, L, T, L, L, + _, L, T, L, _, + L, L, T, L, L, + _, L, L, L, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + {ypos = 8, prob = 127}, + {ypos = 10, prob = 127}, + }, +}) + + +-- Aspen tree from sapling + +mts_save("aspen_tree_from_sapling", { + size = {x = 5, y = 14, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + _, _, _, _, _, + + _, _, B, _, _, + _, _, T, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, _, B, _, _, + _, L, B, L, _, + L, L, B, L, L, + _, L, B, L, _, + L, L, B, L, L, + _, L, B, L, _, + L, L, B, L, L, + _, L, L, L, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + M, L, L, L, M, + _, M, L, M, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + N, M, L, M, N, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + {ypos = 8, prob = 127}, + {ypos = 10, prob = 127}, + }, +}) + + +-- Mapgen emergent jungle tree + +local L = {name = "default:jungleleaves", prob = 255} +local N = {name = "default:jungleleaves", prob = 223} +local M = {name = "default:jungleleaves", prob = 127} +local B = {name = "default:jungletree", prob = 255, force_place = true} +local U = {name = "default:jungletree", prob = 127, force_place = true} + +mts_save("emergent_jungle_tree", { + size = {x = 7, y = 37, z = 7}, + data = { + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + U, _, _, _, _, _, U, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, M, M, M, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, U, B, _, B, U, _, + _, _, U, _, U, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + M, _, _, _, _, _, M, + N, L, _, _, _, L, N, + N, B, L, L, L, B, N, + N, L, L, L, L, L, N, + _, N, N, N, N, N, _, + + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, U, B, B, B, U, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, N, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, _, B, B, N, N, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + _, _, N, B, N, _, _, + _, _, _, B, _, _, _, + _, _, _, B, N, N, N, + N, N, B, B, _, _, _, + _, _, _, B, _, _, _, + _, _, _, B, B, N, N, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + M, _, B, B, B, _, M, + N, _, B, _, B, _, N, + N, L, L, _, L, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, B, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, B, N, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, B, B, B, B, _, _, + _, _, B, B, B, _, _, + M, _, B, _, B, _, M, + N, _, _, _, _, _, N, + N, L, _, _, _, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, U, B, B, B, U, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, _, B, _, _, _, + N, N, N, B, _, _, _, + _, _, _, B, B, N, N, + _, _, _, B, _, _, _, + N, N, B, B, _, _, _, + _, _, _, B, N, N, N, + _, _, _, B, _, _, _, + _, _, N, B, N, _, _, + _, _, _, B, _, _, _, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + M, _, B, B, B, _, M, + N, _, B, _, B, _, N, + N, L, L, _, L, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, _, _, _, _, _, + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, U, B, _, B, U, _, + _, _, U, _, U, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + M, _, _, _, _, _, M, + N, L, _, _, _, L, N, + N, B, L, L, L, B, N, + N, L, L, L, L, L, N, + _, N, N, N, N, N, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + U, _, _, _, _, _, U, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, M, M, M, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, _, _, _, _, _, _, + }, + yslice_prob = { + {ypos = 13, prob = 127}, + {ypos = 14, prob = 127}, + {ypos = 15, prob = 127}, + {ypos = 16, prob = 127}, + {ypos = 17, prob = 127}, + {ypos = 18, prob = 127}, + {ypos = 19, prob = 127}, + {ypos = 20, prob = 127}, + {ypos = 21, prob = 127}, + {ypos = 22, prob = 127}, + {ypos = 23, prob = 127}, + {ypos = 24, prob = 127}, + }, +}) + + +-- Emergent jungle tree from sapling + +local L = {name = "default:jungleleaves", prob = 255} +local N = {name = "default:jungleleaves", prob = 223} +local M = {name = "default:jungleleaves", prob = 127} +local S = {name = "default:jungletree", prob = 255, force_place = true} +local B = {name = "default:jungletree", prob = 255} +local U = {name = "default:jungletree", prob = 127} + +mts_save("emergent_jungle_tree_from_sapling", { + size = {x = 7, y = 37, z = 7}, + data = { + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + U, _, _, _, _, _, U, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, M, M, M, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, _, _, _, _, _, _, + + _, _, _, _, _, _, _, + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, U, B, _, B, U, _, + _, _, U, _, U, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + M, _, _, _, _, _, M, + N, L, _, _, _, L, N, + N, B, L, L, L, B, N, + N, L, L, L, L, L, N, + _, N, N, N, N, N, _, + + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, U, B, B, B, U, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, N, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, _, B, B, N, N, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + _, _, N, B, N, _, _, + _, _, _, B, _, _, _, + _, _, _, B, N, N, N, + N, N, B, B, _, _, _, + _, _, _, B, _, _, _, + _, _, _, B, B, N, N, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + M, _, B, B, B, _, M, + N, _, B, _, B, _, N, + N, L, L, _, L, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, B, B, B, _, _, + _, _, B, S, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, B, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, B, N, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + N, B, B, B, B, _, _, + _, _, B, B, B, _, _, + M, _, B, _, B, _, M, + N, _, _, _, _, _, N, + N, L, _, _, _, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, B, B, B, B, B, _, + _, U, B, B, B, U, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, B, B, B, _, _, + _, _, _, B, _, _, _, + N, N, N, B, _, _, _, + _, _, _, B, B, N, N, + _, _, _, B, _, _, _, + N, N, B, B, _, _, _, + _, _, _, B, N, N, N, + _, _, _, B, _, _, _, + _, _, N, B, N, _, _, + _, _, _, B, _, _, _, + N, N, N, B, _, _, _, + _, _, _, B, _, _, _, + M, _, B, B, B, _, M, + N, _, B, _, B, _, N, + N, L, L, _, L, L, N, + N, L, L, L, L, L, N, + _, N, L, L, L, N, _, + + _, _, _, _, _, _, _, + _, _, B, _, B, _, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, B, B, _, B, B, _, + _, U, B, _, B, U, _, + _, _, U, _, U, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, B, N, + _, _, _, _, _, _, _, + N, B, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, B, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + M, _, _, _, _, _, M, + N, L, _, _, _, L, N, + N, B, L, L, L, B, N, + N, L, L, L, L, L, N, + _, N, N, N, N, N, _, + + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + B, _, _, _, _, _, B, + U, _, _, _, _, _, U, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, N, N, N, + _, _, _, _, _, _, _, + N, N, N, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, N, N, N, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, _, _, _, _, _, _, + _, M, M, M, M, M, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, N, N, N, N, N, _, + _, _, _, _, _, _, _, + }, + yslice_prob = { + {ypos = 13, prob = 127}, + {ypos = 14, prob = 127}, + {ypos = 15, prob = 127}, + {ypos = 16, prob = 127}, + {ypos = 17, prob = 127}, + {ypos = 18, prob = 127}, + {ypos = 19, prob = 127}, + {ypos = 20, prob = 127}, + {ypos = 21, prob = 127}, + {ypos = 22, prob = 127}, + {ypos = 23, prob = 127}, + {ypos = 24, prob = 127}, + }, +}) + + +-- Mapgen small pine tree + +local L = {name = "default:pine_needles", prob = 255} +local M = {name = "default:pine_needles", prob = 223} +local N = {name = "default:pine_needles", prob = 191} +local T = {name = "default:pine_tree", prob = 255, force_place = true} +local B = {name = "default:pine_tree", prob = 255} +local S = {name = "default:snow", prob = 255} + +mts_save("small_pine_tree", { + size = {x = 5, y = 12, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + _, L, L, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + _, _, T, _, _, + L, _, T, _, L, + L, L, T, L, L, + _, L, T, L, _, + _, L, T, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + _, L, L, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + }, +}) + + +-- Small pine tree from sapling + +mts_save("small_pine_tree_from_sapling", { + size = {x = 5, y = 12, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + _, L, L, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, B, _, _, + _, _, T, _, _, + _, _, B, _, _, + _, _, B, _, _, + L, _, B, _, L, + L, L, B, L, L, + _, L, B, L, _, + _, L, B, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + _, L, L, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, _, L, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + {ypos = 4, prob = 127}, + }, +}) + + +-- Snowy small pine tree from sapling + +mts_save("snowy_small_pine_tree_from_sapling", { + size = {x = 5, y = 13, z = 5}, + data = { + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, S, L, S, _, + _, _, S, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + S, L, L, L, S, + _, L, L, L, _, + _, L, L, L, _, + _, S, L, S, _, + _, _, L, _, _, + _, _, S, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, B, _, _, + _, _, T, _, _, + _, _, B, _, _, + _, _, B, _, _, + L, _, B, _, L, + L, L, B, L, L, + S, L, B, L, S, + _, L, B, L, _, + _, L, L, L, _, + _, L, L, L, _, + _, S, L, S, _, + _, _, L, _, _, + _, _, S, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + L, L, _, L, L, + S, L, L, L, S, + _, L, L, L, _, + _, L, L, L, _, + _, S, L, S, _, + _, _, L, _, _, + _, _, S, _, _, + _, _, _, _, _, + _, _, _, _, _, + + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, L, L, L, _, + _, S, L, S, _, + _, _, S, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + _, _, _, _, _, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + }, +}) + + +-- Apple tree log + +mts_save("apple_log", { + size = {x = 4, y = 2, z = 1}, + data = { + {name = "default:tree", param2 = 12, prob = 127}, + {name = "default:tree", param2 = 12}, + {name = "default:tree", param2 = 12}, + {name = "default:tree", param2 = 12}, + {name = "air", prob = 0}, + {name = "flowers:mushroom_brown", prob = 63}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + }, +}) + + +-- Jungletree log + +mts_save("jungle_log", { + size = {x = 5, y = 2, z = 1}, + data = { + {name = "default:jungletree", param2 = 12, prob = 127}, + {name = "default:jungletree", param2 = 12}, + {name = "default:jungletree", param2 = 12}, + {name = "default:jungletree", param2 = 12}, + {name = "default:jungletree", param2 = 12, prob = 127}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + {name = "flowers:mushroom_brown", prob = 127}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + }, +}) + + +-- Pine tree log + +mts_save("pine_log", { + size = {x = 5, y = 2, z = 1}, + data = { + {name = "default:pine_tree", param2 = 12, prob = 127}, + {name = "default:pine_tree", param2 = 12}, + {name = "default:pine_tree", param2 = 12}, + {name = "default:pine_tree", param2 = 12}, + {name = "default:pine_tree", param2 = 12, prob = 127}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + {name = "flowers:mushroom_red", prob = 63}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + }, +}) + + +-- Acacia tree log + +mts_save("acacia_log", { + size = {x = 5, y = 1, z = 1}, + data = { + {name = "default:acacia_tree", param2 = 12, prob = 127}, + {name = "default:acacia_tree", param2 = 12}, + {name = "default:acacia_tree", param2 = 12}, + {name = "default:acacia_tree", param2 = 12}, + {name = "default:acacia_tree", param2 = 12, prob = 127}, + }, +}) + + +-- Aspen tree log + +mts_save("aspen_log", { + size = {x = 5, y = 2, z = 1}, + data = { + {name = "default:aspen_tree", param2 = 12, prob = 127}, + {name = "default:aspen_tree", param2 = 12}, + {name = "default:aspen_tree", param2 = 12}, + {name = "default:aspen_tree", param2 = 12}, + {name = "default:aspen_tree", param2 = 12, prob = 127}, + {name = "air", prob = 0}, + {name = "flowers:mushroom_red", prob = 63}, + {name = "flowers:mushroom_brown", prob = 63}, + {name = "air", prob = 0}, + {name = "air", prob = 0}, + }, +}) + + +-- Large cactus + +local C = {name = "default:cactus", prob = 255, param2 = 20} +local R = {name = "default:cactus", prob = 255, param2 = 20, force_place = true} +local E = {name = "default:cactus", prob = 127, param2 = 20} + +mts_save("large_cactus", { + size = {x = 5, y = 7, z = 1}, + data = { + _, _, R, _, _, + _, _, C, _, _, + _, _, C, _, _, + C, C, C, C, C, + C, _, C, _, C, + E, _, C, _, E, + _, _, C, _, _, + }, +}) + + +-- Papyrus + +mts_save("papyrus", { + size = {x = 1, y = 7, z = 1}, + data = { + {name = "default:dirt", prob = 255, force_place = true}, + {name = "default:dirt", prob = 255, force_place = true}, + {name = "default:papyrus", prob = 255}, + {name = "default:papyrus", prob = 255}, + {name = "default:papyrus", prob = 255}, + {name = "default:papyrus", prob = 255}, + {name = "default:papyrus", prob = 255}, + }, + yslice_prob = { + {ypos = 2, prob = 127}, + {ypos = 3, prob = 127}, + }, +}) + + +-- Bush + +local L = {name = "default:bush_leaves", prob = 255} +local M = {name = "default:bush_leaves", prob = 191} +local N = {name = "default:bush_leaves", prob = 127} +local S = {name = "default:bush_stem", prob = 255, force_place = true} + +mts_save("bush", { + size = {x = 3, y = 3, z = 3}, + data = { + _, _, _, + M, L, M, + N, M, N, + + _, _, _, + L, S, L, + M, L, M, + + _, _, _, + M, L, M, + N, M, N, + }, +}) + + +-- Blueberry bush + +local L = {name = "default:blueberry_bush_leaves_with_berries", prob = 255, force_place = true} +local M = {name = "default:blueberry_bush_leaves_with_berries", prob = 223} +local N = {name = "default:blueberry_bush_leaves_with_berries", prob = 95} + +mts_save("blueberry_bush", { + size = {x = 3, y = 1, z = 3}, + data = { + N, M, N, + + M, L, M, + + N, M, N, + }, +}) + + +-- Acacia bush + +local L = {name = "default:acacia_bush_leaves", prob = 255} +local M = {name = "default:acacia_bush_leaves", prob = 191} +local N = {name = "default:acacia_bush_leaves", prob = 127} +local S = {name = "default:acacia_bush_stem", prob = 255, force_place = true} + +mts_save("acacia_bush", { + size = {x = 3, y = 3, z = 3}, + data = { + _, _, _, + N, M, N, + M, L, M, + + _, _, _, + M, S, M, + L, L, L, + + _, _, _, + N, M, N, + M, L, M, + }, +}) + + +-- Pine bush + +local L = {name = "default:pine_bush_needles", prob = 255} +local M = {name = "default:pine_bush_needles", prob = 191} +local N = {name = "default:pine_bush_needles", prob = 127} +local S = {name = "default:pine_bush_stem", prob = 255, force_place = true} + +mts_save("pine_bush", { + size = {x = 3, y = 3, z = 3}, + data = { + _, _, _, + M, L, M, + N, M, N, + + _, _, _, + L, S, L, + M, L, M, + + _, _, _, + M, L, M, + N, M, N, + }, +}) diff --git a/settingtypes.txt b/settingtypes.txt new file mode 100644 index 0000000..7f6a12b --- /dev/null +++ b/settingtypes.txt @@ -0,0 +1,66 @@ +# This file contains settings of minetest_game that can be changed in +# minetest.conf + +# In creative mode players are able to dig all kind of blocks nearly +# instantly, and have access to unlimited resources. +# Some of the functionality is only available if this setting is present +# at startup. +creative_mode (Creative mode) bool false + +# Flammable nodes will be ignited by nearby igniters. Spreading fire may +# cause severe destruction. +# Spreading fire nodes will disappear when fire is disabled, but +# 'permanent_flame' nodes are unaffected. +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 + +# If enabled, players respawn at the bed they last lay on instead of normal +# spawn. +# This setting is only read at startup. +enable_bed_respawn (Respawn at bed) bool true + +# If enabled, the night can be skipped if more than half of the players are +# in beds. +enable_bed_night_skip (Skip night when sleeping) bool true + +# When TNT explodes, it destroys nearby nodes and damages nearby players. +# This setting is disabled by default on servers. +enable_tnt (TNT) bool true + +# The radius in which nodes will be destroyed by a TNT explosion. +tnt_radius (TNT radius) int 3 0 + +# Sets the behaviour of the inventory items when a player dies. +# bones: Store items in a bone node but drop items if inside protected area. +# drop: Drop items on the ground. +# keep: Player keeps items. +bones_mode (Bones mode) enum bones bones,drop,keep + +# The time in seconds after which the bones of a dead player can be looted +# by everyone. +# Setting this to 0 will disable sharing of bones completely. +share_bones_time (Bones share time) int 1200 0 + +# How much earlier the bones of a dead player can be looted by +# everyone if the player dies in a protected area they don't own. +# 0 to disable. By default it is "share_bones_time" divide by four. +share_bones_time_early (Earlier bones share time) int 300 0 + +# Inform player of condition and location of new bones. +bones_position_message (Inform player about bones) bool false + +# Replaces old stairs with new ones. Only required for older worlds. +enable_stairs_replace_abm (Replace old stairs) bool false + +# If enabled, use the engine's spawn search which does not check for a +# suitable starting biome. +engine_spawn (Use engine spawn search) bool false