diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f847b09 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Compiled source # +################### +*.class +*.jar + +# Eclipse # +########### +*.classpath +*.project + +# System # +########## +.directory +*~ + +# Unknown # +########### +*.orig diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..e587591 --- /dev/null +++ b/COPYING @@ -0,0 +1,621 @@ + 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 \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..93a6ed6 --- /dev/null +++ b/config.yml @@ -0,0 +1,1098 @@ +# +# GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. +# Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) +# +# 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 . +# + +# DO NOT MODIFY THIS VALUE! +version: 2.7.6 + +# GENERAL SECTION +general: + + # Automatic notification of plugin updates + auto-update-notify: true + +# TRANSMUTATION SECTION +transmutation: + + # Rate (in milliseconds) at which blocks are updated + rate: 10 + + # Cool down time between transmutations in seconds + cooldown: 10 + + # What system to use for transmutation cost + # Possible values: xp, vault (requires Vault) + cost: xp + + # Apply Philosopher's Stone to transmutes (true or false) + stone: true + +# SET CIRCLES SECTION +setcircles: + + # Cool down time between using set circles in seconds + cooldown: 10 + + # Limit augmentation size for set circles + limitsize: 5 + + # Limit number of nearby arrows to check + limitarrows: 3 + + # Spawn weapon circle + 1111: + # The cost of this circle in hunger + cost: 5 + # The item ID to be given to the player + # Default: Iron sword + item: 267 + + # Repair Circle + 1133: [] + + # Conversion Circle + 1222: + # The cost of this circle in hunger + cost: 1 + + # Philosopher's Stone Circle + 1233: + # The cost of this circle in hunger + cost: 20 + + # Boron Circle + 1234: + # The cost of this circle in hunger + cost: 1 + # The number of redstone to drop + amount: 1 + + # Soul Circle + 2223: + # The cost of this circle in hunger + cost: 10 + + # Homunculus Circle + 2224: + # The cost of this circle in hunger + cost: 10 + + # Safe Teleportation Circle + 2244: + # The cost of this circle in hunger + cost: 1 + + # Explosion Circle + 2333: + # The cost of this circle in hunger + # Formula: cost + circle size (can be augmented) / 2 + cost: 2 + + # Fire Circle + 3334: + # The cost of this circle in hunger + cost: 5 + # The size of this circle in blocks cubed + size: 3 + + # Fire Explosion Circle + 3344: + # The cost of this circle in hunger + # Formula: cost + circle size (can be augmented) / 2 + cost: 10 + # The size of this circle in blocks cubed + size: 3 + + # Human Transmutation Circle + 3444: + # The cost of this circle in hunger + cost: 20 + + # Bed Circle (0111) + x111: + # The cost of this circle in hunger + cost: 16 + + # Pig Circle (0044) + x044: + # The cost of this circle in hunger + cost: 10 + + # Sheep Circle (0144) + x144: + # The cost of this circle in hunger + cost: 10 + + # Cow Circle (0244) + x244: + # The cost of this circle in hunger + cost: 10 + + # Chicken Circle (0344) + x344: + # The cost of this circle in hunger + cost: 10 + +# PHILOSOPHER'S STONE SECTION +philosopherstone: + + # The multiplier modifier of the philosopher's stone + # Possible values: any integer + # Formula: 1 / (2 to the power of (number of philosopher's stones in inventory) * modifier) + modifier: 1 + +# BLACKLIST SECTION +blacklist: + + # The blacklist used for breaking blocks with transmutation + break: + - 7 + - 19 + - 52 + - 54 + - 61 + - 62 + - 63 + - 64 + - 68 + - 71 + - 90 + - 95 + - 97 + - 117 + + # The blacklist used for placing blocks with transmutation + place: + - 7 + - 8 + - 9 + - 10 + - 11 + - 19 + - 34 + - 36 + - 52 + - 90 + - 95 + - 97 + +# VALUES SECTION (Values of blocks for transmutation) +values: + + # AIR + 0: + 0: 0 + # STONE + 1: + 0: 1 + # GRASS + 2: + 0: 1 + # DIRT + 3: + 0: 1 + # COBBLESTONE + 4: + 0: 1 + # WOOD + 5: + 0: 8 + 1: 8 + 2: 8 + 3: 8 + # SAPLING + 6: + 0: 32 + 1: 32 + 2: 32 + 3: 32 + 4: 32 + # BEDROCK + 7: + 0: 0 + # WATER + 8: + 0: 1 + 1: 0 + 2: 0 + 3: 0 + 4: 0 + 5: 0 + 6: 0 + 7: 0 + 8: 0 + # STATIONARY_WATER + 9: + 0: 1 + 1: 0 + 2: 0 + 3: 0 + 4: 0 + 5: 0 + 6: 0 + 7: 0 + 8: 0 + # LAVA + 10: + 0: 64 + 2: 0 + 4: 0 + 6: 0 + 8: 0 + # STATIONARY_LAVA + 11: + 0: 64 + 2: 0 + 4: 0 + 6: 0 + 8: 0 + # SAND + 12: + 0: 1 + # GRAVEL + 13: + 0: 4 + # GOLD_ORE + 14: + 0: 2048 + # IRON_ORE + 15: + 0: 256 + # COAL_ORE + 16: 128 + # LOG + 17: + 0: 32 + # LEAVES + 18: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + # SPONGE + 19: + 0: 0 + # GLASS + 20: + 0: 1 + # LAPIS_ORE + 21: + 0: 6912 + # LAPIS_BLOCK + 22: + 0: 7776 + # DISPENSER + 23: + 2: 119 + 3: 119 + 4: 119 + 5: 119 + # SANDSTONE + 24: + 0: 4 + 1: 4 + 2: 4 + # NOTE_BLOCK + 25: + 0: 40 + # BED_BLOCK + 26: + 0: 48 + 1: 48 + 2: 48 + 3: 48 + 4: 48 + 8: 48 + # POWERED_RAIL + 27: + 0: 2048 + 1: 2048 + 2: 2048 + 3: 2048 + 4: 2048 + 5: 2048 + 8: 2048 + # DETECTOR_RAIL + 28: + 0: 256 + 1: 256 + 2: 256 + 3: 256 + 4: 256 + 5: 256 + 8: 256 + # PISTON_STICKY_BASE + 29: + 0: 372 + 1: 372 + 2: 372 + 3: 372 + 4: 372 + 5: 372 + # WEB + 30: + 0: 12 + # LONG_GRASS + 31: + 0: 0 + 1: 0 + 2: 0 + # DEAD_BUSH + 32: + 0: 1 + # PISTON_BASE + 33: + 0: 348 + 1: 348 + 2: 348 + 3: 348 + 4: 348 + 5: 348 + # PISTON_EXTENSION + 34: + 0: 0 + 1: 0 + 2: 0 + 3: 0 + 4: 0 + 5: 0 + 8: 0 + 9: 0 + 10: 0 + 11: 0 + 12: 0 + 13: 0 + # WOOL + 35: + 0: 48 + 1: 48 + 2: 48 + 3: 48 + 4: 48 + 5: 48 + 6: 48 + 7: 48 + 8: 48 + 9: 48 + 10: 48 + 11: 48 + 12: 48 + 13: 48 + 14: 48 + 15: 48 + # PISTON_MOVING_PIECE + 36: + 0: 0 + # YELLOW_FLOWER + 37: + 0: 16 + # RED_ROSE + 38: + 0: 16 + # BROWN_MUSHROOM + 39: + 0: 32 + # RED_MUSHROOM + 40: + 0: 32 + # GOLD_BLOCK + 41: + 0: 18432 + # IRON_BLOCK + 42: + 0: 2304 + # DOUBLE_STEP + 43: + 0: 1 + 1: 4 + 2: 8 + 3: 1 + 4: 256 + 5: 1 + # STEP + 44: + 0: 1 + 1: 2 + 2: 4 + 3: 1 + 4: 128 + 5: 1 + # BRICK + 45: + 0: 256 + # TNT + 46: + 0: 964 + # BOOKSHELF + 47: + 0: 336 + # MOSSY_COBBLESTONE + 48: + 0: 145 + # OBSIDIAN + 49: + 0: 64 + # TORCH + 50: + 0: 9 + 1: 9 + 2: 9 + 3: 9 + 4: 9 + 5: 9 + # FIRE + 51: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + 4: 1 + 5: 1 + 6: 1 + 7: 1 + 8: 1 + 9: 1 + 10: 1 + 11: 1 + 12: 1 + 13: 1 + 14: 1 + 15: 1 + # MOB_SPAWNER + 52: + 0: 0 + # WOOD_STAIRS + 53: + 0: 12 + 1: 12 + 2: 12 + 3: 12 + 4: 12 + # CHEST + 54: + 2: 64 + 3: 64 + 4: 64 + 5: 64 + # REDSTONE_WIRE + 55: + 0: 64 + 1: 64 + 2: 64 + 3: 64 + 4: 64 + 5: 64 + 6: 64 + 7: 64 + 8: 64 + 9: 64 + 10: 64 + 11: 64 + 12: 64 + 13: 64 + 14: 64 + 15: 64 + # DIAMOND_ORE + 56: + 0: 8192 + # DIAMOND_BLOCK + 57: + 0: 73728 + # WORKBENCH + 58: + 0: 32 + # CROPS + 59: + 0: 16 + 1: 16 + 2: 16 + 3: 16 + 4: 16 + 5: 16 + 6: 16 + 7: 24 + # SOIL + 60: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + 4: 1 + 5: 1 + 6: 1 + 7: 1 + 8: 1 + # FURNACE + 61: + 2: 8 + 3: 8 + 4: 8 + 5: 8 + # BURNING_FURNACE + 62: + 2: 8 + 3: 8 + 4: 8 + 5: 8 + # SIGN_POST + 63: + 0: 52 + 1: 52 + 2: 52 + 3: 52 + 4: 52 + 5: 52 + 6: 52 + 7: 52 + 8: 52 + 9: 52 + 10: 52 + 11: 52 + 12: 52 + 13: 52 + 14: 52 + 15: 52 + # WOODEN_DOOR + 64: + 0: 24 + 1: 24 + 2: 24 + 3: 24 + 4: 24 + 5: 24 + 6: 24 + 7: 24 + 8: 24 + 9: 24 + 10: 24 + 11: 24 + 12: 24 + 13: 24 + 14: 24 + 15: 24 + # LADDER + 65: + 2: 14 + 3: 14 + 4: 14 + 5: 14 + # RAILS + 66: + 0: 96 + 1: 96 + 2: 96 + 3: 96 + 4: 96 + 5: 96 + 6: 96 + 7: 96 + 8: 96 + 9: 96 + # COBBLESTONE_STAIRS + 67: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + # WALL_SIGN + 68: + 2: 52 + 3: 52 + 4: 52 + 5: 52 + # LEVER + 69: + 6: 5 + 7: 5 + 8: 5 + 9: 5 + 10: 5 + 11: 5 + 12: 5 + 13: 5 + 14: 5 + # STONE_PLATE + 70: + 0: 2 + 1: 2 + # IRON_DOOR_BLOCK + 71: + 0: 768 + 1: 768 + 2: 768 + 3: 768 + 4: 768 + 5: 768 + 6: 768 + 7: 768 + 8: 768 + 9: 768 + 10: 768 + 11: 768 + 12: 768 + 13: 768 + 14: 768 + 15: 768 + # WOOD_PLATE + 72: + 0: 16 + 1: 16 + # REDSTONE_ORE + 73: + 0: 256 + # GLOWING_REDSTONE_ORE + 74: + 0: 256 + # REDSTONE_TORCH_OFF + 75: + 0: 68 + 1: 68 + 2: 68 + 3: 68 + 4: 68 + 5: 68 + # REDSTONE_TORCH_ON + 76: + 0: 68 + 1: 68 + 2: 68 + 3: 68 + 4: 68 + 5: 68 + # STONE_BUTTON + 77: + 0: 2 + 1: 2 + 2: 2 + 3: 2 + 4: 2 + 5: 2 + 6: 2 + 7: 2 + 8: 2 + 9: 2 + 10: 2 + 11: 2 + 12: 2 + 13: 2 + 14: 2 + 15: 2 + # SNOW + 78: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + 4: 1 + 5: 1 + 6: 1 + 7: 1 + 8: 1 + 9: 1 + 10: 1 + 11: 1 + 12: 1 + 13: 1 + 14: 1 + 15: 1 + # ICE + 79: + 0: 1 + # SNOW_BLOCK + 80: + 0: 1 + # CACTUS + 81: + 0: 8 + 1: 8 + 2: 8 + 3: 8 + 4: 8 + 5: 8 + 6: 8 + 7: 8 + 8: 8 + 9: 8 + 10: 8 + 11: 8 + 12: 8 + 13: 8 + 14: 8 + 15: 8 + # CLAY + 82: + 0: 64 + # SUGAR_CANE_BLOCK + 83: + 0: 32 + 1: 32 + 2: 32 + 3: 32 + 4: 32 + 5: 32 + 6: 32 + 7: 32 + 8: 32 + 9: 32 + 10: 32 + 11: 32 + 12: 32 + 13: 32 + 14: 32 + 15: 32 + # JUKEBOX + 84: + 0: 8256 + 1: 8256 + 2: 8256 + 3: 8256 + 4: 8256 + 5: 8256 + 6: 8256 + 7: 8256 + 8: 8256 + 9: 8256 + 10: 8256 + 11: 8256 + # FENCE + 85: + 0: 12 + # PUMPKIN + 86: + 0: 144 + 1: 144 + 2: 144 + 3: 144 + # NETHERRACK + 87: + 0: 1 + # SOUL_SAND + 88: + 0: 49 + # GLOWSTONE + 89: + 0: 1536 + # PORTAL + 90: + 0: 0 + # JACK_O_LANTERN + 91: + 0: 144 + 1: 144 + 2: 144 + 3: 144 + # CAKE_BLOCK + 92: + 0: 363 + 1: 363 + 2: 363 + 3: 363 + 4: 363 + 5: 363 + # DIODE_BLOCK_OFF + 93: + 0: 203 + 1: 203 + 2: 203 + 3: 203 + 4: 203 + 5: 203 + 6: 203 + 7: 203 + 8: 203 + 9: 203 + 10: 203 + 11: 203 + 12: 203 + 13: 203 + 14: 203 + 15: 203 + # DIODE_BLOCK_ON + 94: + 0: 203 + 1: 203 + 2: 203 + 3: 203 + 4: 203 + 5: 203 + 6: 203 + 7: 203 + 8: 203 + 9: 203 + 10: 203 + 11: 203 + 12: 203 + 13: 203 + 14: 203 + 15: 203 + # LOCKED_CHEST + 95: + 0: 0 + # TRAP_DOOR + 96: + 0: 24 + 1: 24 + 2: 24 + 3: 24 + 4: 24 + 5: 24 + 6: 24 + 7: 24 + # MONSTER_EGGS + 97: + 0: 0 + 1: 0 + 2: 0 + # SMOOTH_BRICK + 98: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + # HUGE_MUSHROOM_1 + 99: + 0: 32 + 1: 32 + 2: 32 + 3: 32 + 4: 32 + 5: 32 + 6: 32 + 7: 32 + 8: 32 + 9: 32 + 10: 32 + # HUGE_MUSHROOM_2 + 100: + 0: 32 + 1: 32 + 2: 32 + 3: 32 + 4: 32 + 5: 32 + 6: 32 + 7: 32 + 8: 32 + 9: 32 + 10: 32 + # IRON_FENCE + 101: + 0: 96 + # THIN_GLASS + 102: + 0: 1 + # MELON_BLOCK + 103: + 0: 144 + # PUMPKIN_STEM + 104: + 0: 36 + 1: 36 + 2: 36 + 3: 36 + 4: 36 + 5: 36 + 6: 36 + 7: 36 + # MELON_STEM + 105: + 0: 16 + 1: 16 + 2: 16 + 3: 16 + 4: 16 + 5: 16 + 6: 16 + 7: 16 + # VINE + 106: + 0: 8 + 1: 8 + 2: 8 + 3: 8 + 4: 8 + 5: 8 + 6: 8 + 7: 8 + 8: 8 + 9: 8 + 10: 8 + 11: 8 + 12: 8 + 13: 8 + 14: 8 + 15: 8 + # FENCE_GATE + 107: + 0: 32 + 1: 32 + 2: 32 + 3: 32 + 4: 32 + 5: 32 + 6: 32 + 7: 32 + # BRICK_STAIRS + 108: + 0: 384 + 1: 384 + 2: 384 + 3: 384 + # SMOOTH_STAIRS + 109: + 0: 1 + 1: 1 + 2: 1 + 3: 1 + # MYCEL + 110: + 0: 1 + # WATER_LILY + 111: + 0: 16 + # NETHER_BRICK + 112: + 0: 4 + # NETHER_FENCE + 113: + 0: 4 + # NETHER_BRICK_STAIRS + 114: + 0: 6 + 1: 6 + 2: 6 + 3: 6 + # NETHER_WARTS + 115: + 0: 24 + 1: 24 + 2: 24 + 3: 24 + # ENCHANTMENT_TABLE + 116: + 0: 16736 + # BREWING_STAND + 117: + 0: 1539 + 1: 1539 + 2: 1539 + 3: 1539 + 4: 1539 + 5: 1539 + 6: 1539 + 7: 1539 + # CAULDRON + 118: + 0: 1280 + 1: 1280 + 2: 1280 + 3: 1280 + # ENDER_PORTAL + 119: + 0: 0 + # ENDER_PORTAL_FRAME + 120: + 0: 0 + # ENDER_STONE + 121: + 0: 1 + # DRAGON_EGG + 122: + 0: 139264 + # REDSTONE_LAMP_OFF + 123: + 0: 1792 + # REDSTONE_LAMP_ON + 124: + 0: 1792 + # WOOD_DOUBLE_STEP + 125: + 0: 8 + 1: 8 + 2: 8 + 3: 8 + # WOOD_STEP + 126: + 0: 4 + 1: 4 + 2: 4 + 3: 4 + 4: 4 + # COCOA + 127: + 0: 128 + # SANDSTONE_STAIRS + 128: + 0: 6 + 1: 6 + 2: 6 + 3: 6 + # EMERALD_ORE + 129: + 0: 16384 + # ENDER_CHEST + 130: + 2: 2304 + 3: 2304 + 4: 2304 + 5: 2304 + # TRIPWIRE_HOOK + 131: + 0: 134 + 1: 134 + 2: 134 + 3: 134 + 4: 134 + 5: 134 + 6: 134 + 7: 134 + 8: 134 + 9: 134 + 10: 134 + 11: 134 + 12: 134 + 13: 134 + 14: 134 + 15: 134 + # TRIPWIRE + 132: + 0: 12 + 1: 12 + 2: 12 + 3: 12 + 4: 12 + # EMERALD_BLOCK + 133: + 0: 147456 + # SPRUCE_WOOD_STAIRS + 134: + 0: 12 + 1: 12 + 2: 12 + 3: 12 + # BIRCH_WOOD_STAIRS + 135: + 0: 12 + 1: 12 + 2: 12 + 3: 12 + # JUNGLE_WOOD_STAIRS + 136: + 0: 12 + 1: 12 + 2: 12 + 3: 12 diff --git a/plugin.yml b/plugin.yml index e72cfec..72b4d37 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,31 +1,183 @@ +# +# GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. +# Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) +# +# 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 . +# + name: GeometricMagic main: me.cakenggt.GeometricMagic.GeometricMagic -version: 2.13 -author: cakenggt +version: 2.8.0 +authors: [cakenggt, Hoot215] +softdepend: [Vault, AntiCheat] permissions: - GeometricMagic.circle.*: - description: Gives access to all circles + geometricmagic.*: + description: Gives access to all circles /setcircle and /circles + default: op children: - circle.teleportation: true - circle.micro: true - circle.transmutation: true - circle.set.*: true - circle.teleportation: - description: Allows you to use teleportation circles + geometricmagic.notify: true + geometricmagic.standard: true + geometricmagic.transmutation.*: true + geometricmagic.bypass.*: true + geometricmagic.command.geometricmagic.reload: true + geometricmagic.notify: + description: Notifies you if a newer version of GeometricMagic is available + geometricmagic.standard: + description: Gives access to standard circles /setcircle and /circles default: true - circle.micro: + children: + geometricmagic.teleportation: true + geometricmagic.micro: true + geometricmagic.transmutation.1: true + geometricmagic.storage.*: true + geometricmagic.set: true + geometricmagic.command.geometricmagic: true + geometricmagic.teleportation: + description: Allows you to use teleportation circles + geometricmagic.micro: description: Allows you to use micro circles - default: true - circle.transmutation: - description: Allows you to use transmutation circles - default: true - circle.set.*: + geometricmagic.transmutation.*: + description: Allows you to use all transmutation circles + children: + geometricmagic.transmutation.1: true + geometricmagic.transmutation.3: true + geometricmagic.transmutation.5: true + geometricmagic.transmutation.7: true + geometricmagic.transmutation.9: true + geometricmagic.transmutation.1: + description: Allows you to use transmutation circles of size 1 + geometricmagic.transmutation.3: + description: Allows you to use transmutation circles of size 3 + geometricmagic.transmutation.5: + description: Allows you to use transmutation circles of size 5 + geometricmagic.transmutation.7: + description: Allows you to use transmutation circles of size 7 + geometricmagic.transmutation.9: + description: Allows you to use transmutation circles of size 9 + geometricmagic.storage.*: + description: Allows you to use all storage circles + children: + geometricmagic.storage.1: true + geometricmagic.storage.3: true + geometricmagic.storage.5: true + geometricmagic.storage.7: true + geometricmagic.storage.9: true + geometricmagic.storage.1: + description: Allows you to use storage circles of size 1 + geometricmagic.storage.3: + description: Allows you to use storage circles of size 3 + geometricmagic.storage.5: + description: Allows you to use storage circles of size 5 + geometricmagic.storage.7: + description: Allows you to use storage circles of size 7 + geometricmagic.storage.9: + description: Allows you to use storage circles of size 9 + geometricmagic.set: + description: Allows you to use all set circles and set circle commands + children: + geometricmagic.set.*: true + geometricmagic.command.setcircle: true + geometricmagic.command.circles: true + geometricmagic.command.setcircle: + description: Allows you to use /setcircle + geometricmagic.command.circles: + description: Allows you to use /circles + geometricmagic.command.geometricmagic: + description: Allows you to use /geometricmagic + geometricmagic.command.geometricmagic.reload: + description: 'Allows you to use "/geometricmagic reload"' + geometricmagic.set.*: description: Allows you to use all set circles - default: true children: - circle.set.1234: true + geometricmagic.set.1111: true + geometricmagic.set.1133: true + geometricmagic.set.1222: true + geometricmagic.set.1233: true + geometricmagic.set.1234: true + geometricmagic.set.2223: true + geometricmagic.set.2224: true + geometricmagic.set.2244: true + geometricmagic.set.2333: true + geometricmagic.set.3334: true + geometricmagic.set.3344: true + geometricmagic.set.3444: true + geometricmagic.set.0111: true + geometricmagic.set.0044: true + geometricmagic.set.0144: true + geometricmagic.set.0244: true + geometricmagic.set.0344: true + geometricmagic.set.1111: + description: Allows you to use set circle 1111 + geometricmagic.set.1133: + description: Allows you to use set circle 1133 + geometricmagic.set.1222: + description: Allows you to use set circle 1222 + geometricmagic.set.1233: + description: Allows you to use set circle 1233 + geometricmagic.set.1234: + description: Allows you to use set circle 1234 + geometricmagic.set.2223: + description: Allows you to use set circle 2223 + geometricmagic.set.2224: + description: Allows you to use set circle 2224 + geometricmagic.set.2244: + description: Allows you to use set circle 2244 + geometricmagic.set.2333: + description: Allows you to use set circle 2333 + geometricmagic.set.3334: + description: Allows you to use set circle 3334 + geometricmagic.set.3344: + description: Allows you to use set circle 1133 + geometricmagic.set.3444: + description: Allows you to use set circle 3444 + geometricmagic.set.0111: + description: Allows you to use set circle 0111 + geometricmagic.set.0044: + description: Allows you to use set circle 0044 + geometricmagic.set.0144: + description: Allows you to use set circle 0144 + geometricmagic.set.0244: + description: Allows you to use set circle 0244 + geometricmagic.set.0344: + description: Allows you to use set circle 0344 + geometricmagic.bypass.*: + description: Grants all bypass permissions + children: + geometricmagic.bypass.cooldown: true + geometricmagic.bypass.crafting: true + geometricmagic.bypass.hunger: true + geometricmagic.bypass.sacrifice: true + geometricmagic.bypass.cooldown: + description: Allows you to bypass transmutation and set circle cooldowns + geometricmagic.bypass.crafting: + description: Allows you to bypass crafting being taken away by human transmutation + geometricmagic.bypass.hunger: + description: Allows you to bypass hunger being taken away + geometricmagic.bypass.sacrifice: + description: Allows you to bypass human transmutation sacrificing your alchemy abilities forever commands: - setcircle: - description: This command sets a sacrifice's right-click circle. - permission: GeometricMagic.setcircle - usage: /setcircle 3344 \ No newline at end of file + setcircle: + description: This command sets a sacrifice's right-click circle. + permission: geometricmagic.command.setcircle + usage: "Hold the flint from your inventory in your hand and right-click to cast a set circle. Use /circles to list all set circles. To bind a set circle to the flint use /setcircle ####" + aliases: sc + circles: + description: This command displays a list of set circles. + permission: geometricmagic.command.circles + usage: "/circles" + geometricmagic: + description: This command displays general plugin help or executes the given sub-command. + permission: geometricmagic.command.geometricmagic + usage: "/geometricmagic [Sub-Command]" + aliases: [gem, geom, gmagic] \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagic.java b/src/me/cakenggt/GeometricMagic/GeometricMagic.java index d59b965..8b7530f 100644 --- a/src/me/cakenggt/GeometricMagic/GeometricMagic.java +++ b/src/me/cakenggt/GeometricMagic/GeometricMagic.java @@ -1,138 +1,368 @@ -package me.cakenggt.GeometricMagic; +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ +package me.cakenggt.GeometricMagic; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.Scanner; +import net.milkbowl.vault.economy.Economy; + +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.*; import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; public class GeometricMagic extends JavaPlugin { private Listener playerListener; private Listener entityListener; - private Listener deathListener; - public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){ - if(cmd.getName().equalsIgnoreCase("setcircle")){ // If the player typed /set then do the following... - //[1, 1, 3, 3] - Player player = null; - if (sender instanceof Player) { - player = (Player) sender; - } - if (player == null) { - sender.sendMessage("this command can only be run by a player"); - return false; - } - if (args.length == 0){ - ItemStack oneFlint = new ItemStack(318, 1); - player.getWorld().dropItem(player.getLocation(), oneFlint); - return true; - } - if (args.length != 1){ - sender.sendMessage(cmd.getUsage()); - return false; - } - if (args[0].length() != 4 && args[0].length() != 1){ - sender.sendMessage(cmd.getUsage()); - return false; - } - if (args[0].length() == 1 && args[0].equalsIgnoreCase("0")){ - sender.sendMessage("Casting circles on right click now disabled, set right click to a viable circle to enable"); - String inputString = args[0]; - try { - sacrificeCircle(sender, inputString); - } catch (IOException e) { - e.printStackTrace(); - } - return true; - } - else{ - String inputString = "[" + args[0].charAt(0) + ", " + args[0].charAt(1) + ", " + args[0].charAt(2) + ", " + args[0].charAt(3) + "]"; - try { - sacrificeCircle(sender, inputString); - } catch (IOException e) { - e.printStackTrace(); + private static Economy economy; + File configFile; + public boolean autoUpdateNotify; + public boolean upToDate = true; + + public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) { + + // If the player typed /setcircle then do the following... + if (cmd.getName().equalsIgnoreCase("setcircle")) { + Player player = null; + + if (sender instanceof Player) { + player = (Player) sender; + + if (!player.hasPermission("geometricmagic.command.setcircle")) { + player.sendMessage(ChatColor.RED + "You don't have permission to use this command!"); + return true; + } + + boolean sacrificed = false; + + if (!player.hasPermission("geometricmagic.bypass.sacrifice")) { + try { + sacrificed = checkSacrificed(player); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + if (sacrificed) { + player.sendMessage("You have sacrificed your alchemy abilities forever."); + return true; + } + + boolean sacrifices = false; + try { + sacrifices = checkSacrifices(player); + } catch (IOException e1) { + e1.printStackTrace(); + } + + // check if player has flint and is using the proper arguments + boolean hasFlint = player.getInventory().contains(Material.FLINT); + if ((args.length != 1 || (args[0].length() != 4 && args[0].length() != 1)) && hasFlint && sacrifices) { + sender.sendMessage(ChatColor.RED + cmd.getUsage()); + return true; + } else if (args.length == 0 && !hasFlint && sacrifices) { + // they don't have flint so give them one + ItemStack oneFlint = new ItemStack(318, 1); + player.getWorld().dropItem(player.getLocation(), oneFlint); + return true; + } else if (!sacrifices) { + player.sendMessage(ChatColor.RED + "You must perform a human sacrifice if you wish to use this command."); + return true; + } + + if (args[0].length() == 1 && args[0].equalsIgnoreCase("0")) { + sender.sendMessage("Casting circles on right click now disabled, set right click to a viable circle to enable"); + String inputString = args[0]; + try { + sacrificeCircle(sender, inputString); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + + } else { + String inputString = "[" + args[0].charAt(0) + ", " + args[0].charAt(1) + ", " + args[0].charAt(2) + ", " + args[0].charAt(3) + "]"; + try { + sacrificeCircle(sender, inputString); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + } + + if (player == null) { + sender.sendMessage("This command can only be run by a player"); + return false; + } + } else if (cmd.getName().equalsIgnoreCase("circles")) { + if (sender.hasPermission("geometricmagic.command.circles")) { + sender.sendMessage(ChatColor.GREEN + "1133" + ChatColor.RESET + " Repair Circle"); + sender.sendMessage(ChatColor.GREEN + "1222" + ChatColor.RESET + " Conversion Circle"); + sender.sendMessage(ChatColor.GREEN + "1233" + ChatColor.RESET + " Philosopher's Stone Circle"); + sender.sendMessage(ChatColor.GREEN + "1234" + ChatColor.RESET + " Boron Circle"); + sender.sendMessage(ChatColor.GREEN + "2223" + ChatColor.RESET + " Soul Circle"); + sender.sendMessage(ChatColor.GREEN + "2224" + ChatColor.RESET + " Homunculus Circle"); + sender.sendMessage(ChatColor.GREEN + "2244" + ChatColor.RESET + " Safe Teleportation Circle"); + sender.sendMessage(ChatColor.GREEN + "2333" + ChatColor.RESET + " Explosion Circle"); + sender.sendMessage(ChatColor.GREEN + "3334" + ChatColor.RESET + " Fire Circle"); + sender.sendMessage(ChatColor.GREEN + "3344" + ChatColor.RESET + " Fire Explosion Circle"); + sender.sendMessage(ChatColor.GREEN + "3444" + ChatColor.RESET + " Human Transmutation Circle"); + sender.sendMessage(ChatColor.GREEN + "0111" + ChatColor.RESET + " Bed Circle"); + sender.sendMessage(ChatColor.GREEN + "0044" + ChatColor.RESET + " Pig Circle"); + sender.sendMessage(ChatColor.GREEN + "0144" + ChatColor.RESET + " Sheep Circle"); + sender.sendMessage(ChatColor.GREEN + "0244" + ChatColor.RESET + " Cow Circle"); + sender.sendMessage(ChatColor.GREEN + "0344" + ChatColor.RESET + " Chicken Circle"); + } else + sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!"); + return true; + } else if (cmd.getName().equalsIgnoreCase("geometricmagic")) { + if (sender.hasPermission("geometricmagic.command.geometricmagic")) { + if (args.length == 0) { + sender.sendMessage(ChatColor.GREEN + "*********** GeometricMagic Help ***********"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.GRAY + "************* User Commands *************"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.GRAY + "*" + ChatColor.YELLOW + " /geometricmagic" + ChatColor.WHITE + " - Display this help dialogue"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.GRAY + "*" + ChatColor.YELLOW + " /setcircle <####>" + ChatColor.WHITE + " - Bind set circle #### to flint. 0 resets"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.GRAY + "*" + ChatColor.YELLOW + " /circles" + ChatColor.WHITE + " - List all set circles"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.GRAY + "*****************************************"); + if (sender.hasPermission("geometricmagic.command.geometricmagic.reload")) { + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.RED + "************* Admin Commands ************"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.RED + "*" + ChatColor.YELLOW + " /geometricmagic reload" + ChatColor.WHITE + " - Reload config file"); + sender.sendMessage(ChatColor.GREEN + "*" + ChatColor.RED + "*****************************************"); + } + sender.sendMessage(ChatColor.GREEN + "******************************************"); + return true; + } + else if (args.length == 1) { + if (args[0].equalsIgnoreCase("reload")) { + if (sender.hasPermission("geometricmagic.command.geometricmagic.reload")) { + reloadConfig(); + sender.sendMessage(ChatColor.GREEN + "Config reload successfully!"); + return true; + } + else { + sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!"); + return true; + } + } + else + return false; + } + else if (args.length > 1) + return false; + } + else { + sender.sendMessage(ChatColor.RED + "You don't have permission to use this command!"); + return true; } - return true; - } - } //If this has happened the function will break and return true. if this hasn't happened the a value of false will be returned. - return false; - } - - public void sacrificeCircle (CommandSender sender, String inputString) throws IOException{ - //System.out.println("sacrificeCircle for " + inputString); - File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); - if (myFile.exists()){ - Scanner inputFileCheck = new Scanner(myFile); - int j = 0; - while (inputFileCheck.hasNext()) { - inputFileCheck.nextLine(); - j++; - } - int size = (j + 1) / 2; - //System.out.println("size of sacrifices file " + size); - String[] nameArray = new String[size]; - String[] circleArray = new String[size]; - inputFileCheck.close(); - //System.out.println("inputFileCheck closed"); - Scanner inputFile = new Scanner(myFile); - //System.out.println("inputFile opened"); - for (int i = 0; i < size; i++) { - nameArray[i] = inputFile.nextLine(); - circleArray[i] = inputFile.nextLine(); - } - //System.out.println("nameArray[0] is " + nameArray[0]); - //System.out.println("circleArray[0] is " + circleArray[0]); - for (int i = 0; i < size; i++) { - if (nameArray[i].equalsIgnoreCase(sender.getName())){ - circleArray[i] = inputString; - sender.sendMessage("set-circle " + inputString + " added successfully!"); - } - } - //System.out.println("nameArray[0] is " + nameArray[0]); - //System.out.println("circleArray[0] is " + circleArray[0]); - inputFile.close(); - PrintWriter outputFile = new PrintWriter("plugins/GeometricMagic/sacrifices.txt"); - for (int i = 0; i < size; i++) { - outputFile.println(nameArray[i]); - outputFile.println(circleArray[i]); - } - outputFile.close(); } - else{ + // If this has happened the function will break and return true. if this + // hasn't happened the a value of false will be returned. + return false; + } + + public void sacrificeCircle(CommandSender sender, String inputString) throws IOException { + // System.out.println("sacrificeCircle for " + inputString); + File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); + if (myFile.exists()) { + Scanner inputFileCheck = new Scanner(myFile); + int j = 0; + while (inputFileCheck.hasNext()) { + inputFileCheck.nextLine(); + j++; + } + int size = (j + 1) / 2; + // System.out.println("size of sacrifices file " + size); + String[] nameArray = new String[size]; + String[] circleArray = new String[size]; + inputFileCheck.close(); + // System.out.println("inputFileCheck closed"); + Scanner inputFile = new Scanner(myFile); + // System.out.println("inputFile opened"); + for (int i = 0; i < size; i++) { + nameArray[i] = inputFile.nextLine(); + circleArray[i] = inputFile.nextLine(); + } + // System.out.println("nameArray[0] is " + nameArray[0]); + // System.out.println("circleArray[0] is " + circleArray[0]); + for (int i = 0; i < size; i++) { + if (nameArray[i].equalsIgnoreCase(sender.getName())) { + circleArray[i] = inputString; + sender.sendMessage("set-circle " + inputString + " added successfully!"); + } + } + // System.out.println("nameArray[0] is " + nameArray[0]); + // System.out.println("circleArray[0] is " + circleArray[0]); + inputFile.close(); + PrintWriter outputFile = new PrintWriter("plugins/GeometricMagic/sacrifices.txt"); + for (int i = 0; i < size; i++) { + outputFile.println(nameArray[i]); + outputFile.println(circleArray[i]); + } + outputFile.close(); + } else { return; } - } - - - public void onDisable() { - // TODO: Place any custom disable code here. - System.out.println(this + " is now disabled!"); - } - - public void onEnable() { - // TODO: Place any custom enable code here, such as registering events - playerListener = new GeometricMagicPlayerListener(); - entityListener = new GeometricMagicDamageListener(); - deathListener = new GeometricMagicPlayerDeathListener(); - getServer().getPluginManager().registerEvents(playerListener, this); - getServer().getPluginManager().registerEvents(entityListener, this); - getServer().getPluginManager().registerEvents(deathListener, this); - ShapelessRecipe portalRecipe = new ShapelessRecipe(new ItemStack(Material.FIRE, 64)).addIngredient(Material.PORTAL); - getServer().addRecipe(portalRecipe); - System.out.println(this + " is now enabled!"); - } - - - + } + public static boolean checkSacrifices(Player player) throws IOException { + File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); + if (!myFile.exists()) { + return false; + } + Scanner inputFile = new Scanner(myFile); + while (inputFile.hasNextLine()) { + String name = inputFile.nextLine(); + if (name.equals(player.getName())) { + // close this before we return + inputFile.close(); + return true; + } + inputFile.nextLine(); + } + inputFile.close(); + return false; + // playername + // [1, 1, 1, 2] + } + + public static boolean checkSacrificed(Player player) throws IOException { + File myFile = new File("plugins/GeometricMagic/sacrificed.txt"); + if (!myFile.exists()) { + return false; + } + Scanner inputFile = new Scanner(myFile); + while (inputFile.hasNextLine()) { + String name = inputFile.nextLine(); + if (name.equals(player.getName())) { + // close this before we return + inputFile.close(); + return true; + } + } + inputFile.close(); + return false; + // playername + } + + @Override + public void onDisable() { + System.out.println(this + " is now disabled!"); + } + + @Override + public void onEnable() { + + configFile = new File(getDataFolder(), "config.yml"); + + // Copy default config file if it doesn't exist + if (!configFile.exists()) { + saveDefaultConfig(); + System.out.println("[GeometricMagic] Config file generated!"); + } + else { + try { + GeometricMagicConfigUpdater.updateConfig(this); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // Transmutation mode: Vault + if (getConfig().getString("transmutation.cost").toString().equalsIgnoreCase("vault")) { + // Vault Support + if (!setupEconomy()) { + System.out.println("[GeometricMagic] ERROR: You have your transmutation system set to Vault, and yet you don't have Vault. Disabling plugin!"); + getServer().getPluginManager().disablePlugin(this); + } else { + System.out.println("[GeometricMagic] Transmutation cost system set to Vault"); + + // Register events + playerListener = new GeometricMagicPlayerListener(this); + entityListener = new GeometricMagicDamageListener(this); + getServer().getPluginManager().registerEvents(playerListener, this); + getServer().getPluginManager().registerEvents(entityListener, this); + ShapelessRecipe portalRecipe = new ShapelessRecipe(new ItemStack(Material.FIRE, 64)).addIngredient(Material.PORTAL); + getServer().addRecipe(portalRecipe); + System.out.println(this + " is now enabled!"); + } + } + // Transmutation mode: XP + else if (getConfig().getString("transmutation.cost").toString().equalsIgnoreCase("xp")) { + System.out.println("[GeometricMagic] Transmutation cost system set to XP"); + + // Register events + playerListener = new GeometricMagicPlayerListener(this); + entityListener = new GeometricMagicDamageListener(this); + getServer().getPluginManager().registerEvents(playerListener, this); + getServer().getPluginManager().registerEvents(entityListener, this); + ShapelessRecipe portalRecipe = new ShapelessRecipe(new ItemStack(Material.FIRE, 64)).addIngredient(Material.PORTAL); + getServer().addRecipe(portalRecipe); + System.out.println(this + " is now enabled!"); + } + // Transmutation mode: Unknown + else { + System.out.println("[GeometricMagic] ERROR: You have your transmutation cost system set to an unknown value. Disabling plugin!"); + getServer().getPluginManager().disablePlugin(this); + } + + // Plugin metrics + startPluginMetrics(); + + // Get plugin version for auto-update + int pluginVersion = Integer.parseInt(this.getDescription().getVersion().replace(".", "")); + + // Start auto-update if applicable + if (getConfig().getBoolean("auto-update-notify")) { + new Thread((new GeometricMagicAutoUpdater(this, pluginVersion))).start(); + } + } + // Vault Support + private boolean setupEconomy() { + RegisteredServiceProvider economyProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class); + if (economyProvider != null) { + economy = economyProvider.getProvider(); + } + + return (economy != null); + } + // Vault Support + public static Economy getEconomy() { + return economy; + } + private void startPluginMetrics() { + try { + Metrics metrics = new Metrics(this); + metrics.start(); + } catch (IOException e) { + // Failed to submit the stats :-( + } + } } \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicAutoUpdater.java b/src/me/cakenggt/GeometricMagic/GeometricMagicAutoUpdater.java new file mode 100644 index 0000000..10f6899 --- /dev/null +++ b/src/me/cakenggt/GeometricMagic/GeometricMagicAutoUpdater.java @@ -0,0 +1,66 @@ +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ + +package me.cakenggt.GeometricMagic; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Scanner; + + + +public class GeometricMagicAutoUpdater implements Runnable { + GeometricMagic plugin; + private int pluginVersion; + + public GeometricMagicAutoUpdater(GeometricMagic instance, int v) { + plugin = instance; + pluginVersion = v; + } + + public void run() { + while (true) { + String rawVersion = null; + + try { + URL url = new URL("http://dl.dropbox.com/u/56151340/BukkitPlugins/GeometricMagic/latest.txt"); + Scanner scanner = new Scanner(url.openStream()); + rawVersion = scanner.next(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + int latestVersion = Integer.parseInt(rawVersion.replace(".", "")); + + if (latestVersion > pluginVersion) { + plugin.upToDate = false; + System.out.println("[GeometricMagic] A newer version of GeometricMagic is available!"); + } + else + System.out.println("[GeometricMagic] Plugin is up to date!"); + try { + Thread.sleep(3600000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicConfigUpdater.java b/src/me/cakenggt/GeometricMagic/GeometricMagicConfigUpdater.java new file mode 100644 index 0000000..585f5aa --- /dev/null +++ b/src/me/cakenggt/GeometricMagic/GeometricMagicConfigUpdater.java @@ -0,0 +1,270 @@ +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ + +package me.cakenggt.GeometricMagic; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +// This class is basically intended for use as an automatic config updater, since +// the normal saveConfig() screws up all of the formatting. Unfortunately, this +// method also screws up the formatting a little bit, but it works slightly better. + +public class GeometricMagicConfigUpdater { + static GeometricMagic plugin; + + public static void updateConfig(GeometricMagic instance) throws IOException { + plugin = instance; + + // If the config is not updated + if (!isUpdated()) { + // If the config is not updated to version 2.7.3 + if (!plugin.getConfig().isSet("version")) { + System.out.println("[GeometricMagic] Updating config to v2.7.3..."); + + File myFile = new File("plugins/GeometricMagic/config.yml"); + if (myFile.exists()) { + FileWriter fileWriter = new FileWriter(myFile, true); + PrintWriter file = new PrintWriter(fileWriter); + file.println(); + file.println("# DO NOT MODIFY THIS VALUE!"); + file.println("version: 2.7.3"); + file.println(); + file.println("# GENERAL SECTION"); + file.println("general:"); + file.println(); + file.println(" # Automatic notification of plugin updates"); + file.println(" auto-update-notify: true"); + file.close(); + + plugin.reloadConfig(); + } + else + return; + + if (!isUpdated()) { + updateConfig(instance); + return; + } + } + else if (plugin.getConfig().getString("version").equals("2.7.3")) { + System.out.println("[GeometricMagic] Updating config to v2.7.4..."); + List strList = new ArrayList(); + + File myFile = new File("plugins/GeometricMagic/config.yml"); + if (myFile.exists()) { + Scanner in = new Scanner(myFile); + while (in.hasNextLine()) { + String nextLine = in.nextLine(); + if (!nextLine.contains("version:") + && !nextLine.contains("# DO NOT MODIFY THIS VALUE!")) + strList.add(nextLine); + else + in.nextLine(); + } + in.close(); + + Files.delete(Paths.get("plugins/GeometricMagic/config.yml")); + PrintWriter out = new PrintWriter(new File("plugins/GeometricMagic/config.yml")); + for (String s : strList) { + out.println(s); + } + + out.println(); + out.println("# DO NOT MODIFY THIS VALUE!"); + out.println("version: 2.7.4"); + out.close(); + + plugin.reloadConfig(); + } + else + return; + + if (!isUpdated()) { + updateConfig(instance); + return; + } + } + else if (plugin.getConfig().getString("version").equals("2.7.4")) { + System.out.println("[GeometricMagic] Updating config to v2.7.5..."); + List strList = new ArrayList(); + + File myFile = new File("plugins/GeometricMagic/config.yml"); + if (myFile.exists()) { + Scanner in = new Scanner(myFile); + while (in.hasNextLine()) { + String nextLine = in.nextLine(); + if (!nextLine.contains("version:") + && !nextLine.contains("# DO NOT MODIFY THIS VALUE!")) + strList.add(nextLine); + else + in.nextLine(); + } + in.close(); + + Files.delete(Paths.get("plugins/GeometricMagic/config.yml")); + PrintWriter out = new PrintWriter(new File("plugins/GeometricMagic/config.yml")); + for (String s : strList) { + out.println(s); + } + + out.println(); + out.println("# DO NOT MODIFY THIS VALUE!"); + out.println("version: 2.7.5"); + out.close(); + + plugin.reloadConfig(); + } + else + return; + + if (!isUpdated()) { + updateConfig(instance); + return; + } + } + else if (plugin.getConfig().getString("version").equals("2.7.5")) { + System.out.println("[GeometricMagic] Updating config to v2.7.6..."); + List strList = new ArrayList(); + + File myFile = new File("plugins/GeometricMagic/config.yml"); + if (myFile.exists()) { + Scanner in = new Scanner(myFile); + while (in.hasNextLine()) { + String nextLine = in.nextLine(); + if (!nextLine.contains("version:") + && !nextLine.contains("# DO NOT MODIFY THIS VALUE!") + && !nextLine.contains("# TRANSMUTATION SECTION") + && !nextLine.contains("transmutation:") + && !nextLine.contains(" # Cool down time between transmutations in seconds") + && !nextLine.contains(" cooldown:") + && !nextLine.contains(" # What system to use for transmutation cost") + && !nextLine.contains(" # Possible values: xp, vault (requires Vault)") + && !nextLine.contains(" cost: xp") + && !nextLine.contains(" # Apply Philosopher's Stone to transmutes (true or false)") + && !nextLine.contains(" stone: true")) + strList.add(nextLine); + else + in.nextLine(); + } + in.close(); + + Files.delete(Paths.get("plugins/GeometricMagic/config.yml")); + PrintWriter out = new PrintWriter(new File("plugins/GeometricMagic/config.yml")); + for (String s : strList) { + out.println(s); + } + + out.println(); + out.println("# DO NOT MODIFY THIS VALUE!"); + out.println("version: 2.7.6"); + out.println(); + out.println("# TRANSMUTATION SECTION"); + out.println("transmutation:"); + out.println(); + out.println(" # Rate (in milliseconds) at which blocks are updated"); + out.println(" rate: 10"); + out.println(); + out.println(" # Cool down time between transmutations in seconds"); + out.println(" cooldown: 10"); + out.println(); + out.println(" # What system to use for transmutation cost"); + out.println(" # Possible values: xp, vault (requires Vault)"); + out.println(" cost: xp"); + out.println(); + out.println(" # Apply Philosopher's Stone to transmutes (true or false)"); + out.println(" stone: true"); + out.println(); + out.close(); + + plugin.reloadConfig(); + } + else + return; + + if (!isUpdated()) { + updateConfig(instance); + return; + } + } + else if (plugin.getConfig().getString("version").equals("2.7.6")) { + System.out.println("[GeometricMagic] Updating config to v2.8.0..."); + List strList = new ArrayList(); + + File myFile = new File("plugins/GeometricMagic/config.yml"); + if (myFile.exists()) { + Scanner in = new Scanner(myFile); + while (in.hasNextLine()) { + String nextLine = in.nextLine(); + if (!nextLine.contains("version:") + && !nextLine.contains("# DO NOT MODIFY THIS VALUE!")) + strList.add(nextLine); + else + in.nextLine(); + } + in.close(); + + Files.delete(Paths.get("plugins/GeometricMagic/config.yml")); + PrintWriter out = new PrintWriter(new File("plugins/GeometricMagic/config.yml")); + for (String s : strList) { + out.println(s); + } + + out.println(); + out.println("# DO NOT MODIFY THIS VALUE!"); + out.println("version: 2.8.0"); + out.close(); + + plugin.reloadConfig(); + } + else + return; + + if (!isUpdated()) { + updateConfig(instance); + return; + } + } + } + // If the config is updated + else { + System.out.println("[GeometricMagic] No config update needed"); + return; + } + + System.out.println("[GeometricMagic] Config updated successfully!"); + } + + public static boolean isUpdated() { + if (plugin.getConfig().isSet("version") + && plugin.getDescription().getVersion() + .equals(plugin.getConfig().getString("version"))) { + return true; + } + else { + return false; + } + } +} \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicDamageListener.java b/src/me/cakenggt/GeometricMagic/GeometricMagicDamageListener.java index b2ea50f..1bc69d9 100644 --- a/src/me/cakenggt/GeometricMagic/GeometricMagicDamageListener.java +++ b/src/me/cakenggt/GeometricMagic/GeometricMagicDamageListener.java @@ -1,46 +1,81 @@ -package me.cakenggt.GeometricMagic; +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ +package me.cakenggt.GeometricMagic; import org.bukkit.Material; import org.bukkit.entity.*; -//import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +public class GeometricMagicDamageListener implements Listener { + private GeometricMagic plugin; + public GeometricMagicDamageListener(GeometricMagic plugin) { + this.plugin = plugin; + } + + public GeometricMagic getPlugin() { + return plugin; + } -public class GeometricMagicDamageListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onEntityDamage(EntityDamageEvent event) { - //System.out.println("entity damage event"); + // System.out.println("entity damage event"); Entity entity = event.getEntity(); int damage = event.getDamage(); - if (entity instanceof Player){ - //System.out.println("instance of player"); + + if (entity instanceof Player) { + // System.out.println("instance of player"); Player player = (Player) entity; int health = player.getHealth(); - while (player.getInventory().contains(Material.FIRE)){ - //System.out.println("contains fire"); - if (health - damage <= 0){ + + PlayerInventory playerInventory = player.getInventory(); + + while (playerInventory.contains(Material.FIRE)) { + + // System.out.println("contains fire"); + if (health - damage <= 0) { boolean removedFire = false; - for (int i = 0; i < player.getInventory().getSize() && !removedFire; i++ ){ - if (player.getInventory().getItem(i).getType() == Material.FIRE){ - //System.out.println("removed a fire"); - int amount = player.getInventory().getItem(i).getAmount(); - player.getInventory().getItem(i).setAmount(amount - 1); - if (amount-1 <= 0){ - player.getInventory().clear(i); + + for (int i = 0; i < playerInventory.getSize() && !removedFire; i++) { + ItemStack inventoryItem = playerInventory.getItem(i); + if (inventoryItem != null) { + if (inventoryItem.getType() == Material.FIRE) { + // System.out.println("removed a fire"); + int amount = inventoryItem.getAmount(); + inventoryItem.setAmount(amount - 1); + if (amount - 1 <= 0) { + playerInventory.clear(i); + } + damage = damage - health; + health = 20; + player.setHealth(20); + removedFire = true; } - damage = damage - health; - health = 20; - player.setHealth(20); - removedFire = true; } } - } - else{ + + } else { event.setDamage(damage); return; } diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerDeathListener.java b/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerDeathListener.java deleted file mode 100644 index 34f6ac0..0000000 --- a/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerDeathListener.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.cakenggt.GeometricMagic; - - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDeathEvent; -//import org.bukkit.event.player.PlayerListener; -import org.bukkit.inventory.ItemStack; - - - -public class GeometricMagicPlayerDeathListener implements Listener { - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerDeath(EntityDeathEvent event) { - if (event.getEntity() instanceof Player){ - Player player = (Player) event.getEntity(); - int level = player.getLevel(); - while (level > 5){ - if (level > 13824){ - ItemStack oneDiamondBlock = new ItemStack(Material.DIAMOND_BLOCK, 1); - player.getWorld().dropItem(player.getLocation(), oneDiamondBlock); - level -= 13824; - } - else if (level > 1568){ - ItemStack one84 = new ItemStack(84, 1); - player.getWorld().dropItem(player.getLocation(), one84); - level -= 1568; - } - else if (level > 153){ - ItemStack one29 = new ItemStack(29, 1); - player.getWorld().dropItem(player.getLocation(), one29); - level -= 153; - } - else if (level > 12){ - ItemStack one70 = new ItemStack(70, 1); - player.getWorld().dropItem(player.getLocation(), one70); - level -= 12; - } - else if (level > 1){ - ItemStack one2 = new ItemStack(2, 1); - player.getWorld().dropItem(player.getLocation(), one2); - level -= 1; - } - } - } - } -} \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerListener.java b/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerListener.java index 9ed2d71..046de92 100644 --- a/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerListener.java +++ b/src/me/cakenggt/GeometricMagic/GeometricMagicPlayerListener.java @@ -1,58 +1,142 @@ +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ + package me.cakenggt.GeometricMagic; import java.io.*; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Scanner; +import net.h31ix.anticheat.api.AnticheatAPI; +import net.h31ix.anticheat.manage.CheckType; +import net.milkbowl.vault.economy.Economy; + +import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.*; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.*; -//import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; - +import org.bukkit.plugin.PluginManager; public class GeometricMagicPlayerListener implements Listener { + static GeometricMagic plugin = new GeometricMagic(); + + public GeometricMagicPlayerListener(GeometricMagic instance) { + plugin = instance; + } + + public static Economy economy = null; + private static HashMap mapCoolDowns = new HashMap(); + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayLogin(PlayerLoginEvent event) { + final String playerName = event.getPlayer().getName(); + + if (event.getPlayer().hasPermission("geometricmagic.notify")) { + if (!plugin.upToDate && plugin.getConfig().getBoolean("general.auto-update-notify")) { + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + + public void run() { + if (plugin.getServer().getPlayer(playerName) != null) { + plugin.getServer().getPlayer(playerName).sendMessage( + ChatColor.GREEN + + "A newer version of"+ ChatColor.RED + + " GeometricMagic" + ChatColor.GREEN + + " is available!"); + plugin.getServer().getPlayer(playerName).sendMessage( + ChatColor.GREEN + + "If you cannot find a newer version," + + " check in the comments for a Dropbox link"); + } + } + }, 60L); + } + } + } + @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerInteract(PlayerInteractEvent event) { - //System.out.println("is playerinteractevent"); - if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR){ - //System.out.println("doesn't equal click block or click air"); + + // System.out.println("is playerinteractevent"); + if (event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR) { + // System.out.println("doesn't equal click block or click air"); return; } - boolean sacrifices = false; + + Player player = event.getPlayer(); + boolean sacrificed = false; + + if (!player.hasPermission("geometricmagic.bypass.sacrifice")) { + try { + sacrificed = GeometricMagic.checkSacrificed(player); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + boolean sacrifices = false; try { - sacrifices = checkSacrifices(event.getPlayer()); - sacrificed = checkSacrificed(event.getPlayer()); + sacrifices = GeometricMagic.checkSacrifices(player); } catch (IOException e1) { e1.printStackTrace(); } - if (sacrificed){ - //System.out.println("is sacrificed"); - return; - } - Block actBlock = event.getPlayer().getLocation().getBlock(); - if (event.getAction() == Action.RIGHT_CLICK_BLOCK){ - //System.out.println("right clicked block"); - if (event.getClickedBlock().getType() == Material.WORKBENCH && sacrifices) - event.getClickedBlock().setType(Material.AIR); + + Block actBlock = player.getLocation().getBlock(); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (event.getClickedBlock().getType() == Material.WORKBENCH && (sacrifices && !sacrificed) && !player.hasPermission("geometricmagic.bypass.crafting")) { + // cancel event instead of turning block into air + player.sendMessage("You have already sacrificed your crafting abilities. You must sacrifice your alchemy forever to get them back by performing another human transmutation."); + event.setCancelled(true); + } actBlock = event.getClickedBlock(); } - if (event.getAction() == Action.RIGHT_CLICK_AIR && event.getPlayer().getItemInHand().getType() == Material.FLINT ){ - //System.out.println("is leftclickair"); - actBlock = event.getPlayer().getTargetBlock(null, 120); + + ItemStack inHand = event.getPlayer().getItemInHand(); + Material inHandType = inHand.getType(); + + if ((sacrificed && (inHandType == Material.FLINT || (actBlock.getType() == Material.REDSTONE_WIRE && inHand.getAmount() == 0))) && !player.hasPermission("geometricmagic.bypass.sacrifice")) { + player.sendMessage("You have sacrificed your alchemy abilities forever."); + return; } - Player player = event.getPlayer(); + + if (event.getAction() == Action.RIGHT_CLICK_AIR && inHandType == Material.FLINT) { + actBlock = player.getTargetBlock(null, 120); + } + World world = player.getWorld(); try { isCircle(player, world, actBlock); @@ -61,839 +145,1518 @@ public void onPlayerInteract(PlayerInteractEvent event) { } } - public static void isCircle (Player player, World world, Block actBlock) throws IOException { - //System.out.println("isCircle?"); - if (actBlock.getType() == Material.REDSTONE_WIRE && player.getItemInHand().getAmount() == 0 && !checkSacrificed(player)){ - //System.out.println("isCircle"); + public static void isCircle(Player player, World world, Block actBlock) throws IOException { + // System.out.println("isCircle?"); + if (actBlock.getType() == Material.REDSTONE_WIRE && player.getItemInHand().getAmount() == 0) { + // System.out.println("isCircle"); circleChooser(player, world, actBlock); } - boolean sacrifices = checkSacrifices(player); - if (player.getItemInHand().getType() == Material.FLINT && sacrifices && !checkSacrificed(player)){ + if (player.getItemInHand().getType() == Material.FLINT) { + + // set circle cool down + if (!player.hasPermission("geometricmagic.bypass.cooldown")) { + int coolDown = plugin.getConfig().getInt("setcircles.cooldown"); + if (mapCoolDowns.containsKey(player.getName() + " set circle")) { + long diff = (System.currentTimeMillis() - mapCoolDowns.get(player.getName() + " set circle")) / 1000; + if (diff < coolDown) { + // still cooling down + player.sendMessage(coolDown - diff + " seconds before you can do that again."); + return; + } + } + mapCoolDowns.put(player.getName() + " set circle", System.currentTimeMillis()); + } + File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); - Scanner inputFile = new Scanner(myFile); String circle = "[0, 0, 0, 0]"; - while (inputFile.hasNextLine()){ - String name = inputFile.nextLine(); - if (name.equals(player.getName())){ - circle = inputFile.nextLine(); + if (myFile.exists()) { + Scanner inputFile = new Scanner(myFile); + while (inputFile.hasNextLine()) { + String name = inputFile.nextLine(); + if (name.equals(player.getName())) { + circle = inputFile.nextLine(); + } else + inputFile.nextLine(); + } + inputFile.close(); + } else { + return; + } + + try { + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + if (circle.equals("0")) { + circleChooser(player, world, actBlock); } else - inputFile.nextLine(); + setCircleEffects(player, player.getWorld(), player.getLocation().getBlock(), actBlock, circle); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } catch (IOException e1) { + e1.printStackTrace(); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } + + } else + return; + } + + public static void circleChooser(Player player, World world, Block actBlock) { + Block northBlock = actBlock.getRelative(0, 0, -1); + Block southBlock = actBlock.getRelative(0, 0, 1); + Block eastBlock = actBlock.getRelative(1, 0, 0); + Block westBlock = actBlock.getRelative(-1, 0, 0); + + // teleportation circle + if (northBlock.getType() == Material.REDSTONE_WIRE && southBlock.getType() == Material.REDSTONE_WIRE && eastBlock.getType() == Material.REDSTONE_WIRE + && westBlock.getType() == Material.REDSTONE_WIRE) { + if (player.hasPermission("geometricmagic.teleportation")) { + // System.out.println("teleportation"); + teleportationCircle(player, world, actBlock); + } else + player.sendMessage("You do not have permission to use this circle"); + + // micro circle + } else if (northBlock.getType() != Material.REDSTONE_WIRE && southBlock.getType() != Material.REDSTONE_WIRE && eastBlock.getType() != Material.REDSTONE_WIRE + && westBlock.getType() != Material.REDSTONE_WIRE && actBlock.getRelative(-3, 0, 0).getType() != Material.REDSTONE_WIRE + && actBlock.getRelative(3, 0, 0).getType() != Material.REDSTONE_WIRE && actBlock.getRelative(0, 0, -3).getType() != Material.REDSTONE_WIRE + && actBlock.getRelative(0, 0, 3).getType() != Material.REDSTONE_WIRE) { + if (player.hasPermission("geometricmagic.micro")) { + // System.out.println("micro"); + microCircle(player, world, actBlock); + } else + player.sendMessage("You do not have permission to use this circle"); + + // transmutation circle + } else if ((northBlock.getType() == Material.REDSTONE_WIRE && southBlock.getType() == Material.REDSTONE_WIRE && eastBlock.getType() != Material.REDSTONE_WIRE && westBlock.getType() != Material.REDSTONE_WIRE) + || (northBlock.getType() != Material.REDSTONE_WIRE && southBlock.getType() != Material.REDSTONE_WIRE && eastBlock.getType() == Material.REDSTONE_WIRE && westBlock.getType() == Material.REDSTONE_WIRE)) { + + // transmutation circle size permissions + // - allows use of all circles smaller than then the max + // size permission node they have + int transmutationCircleSize = 1; + if (player.hasPermission("geometricmagic.transmutation.9")) { + transmutationCircleSize = 9; + } else if (player.hasPermission("geometricmagic.transmutation.7")) { + transmutationCircleSize = 7; + } else if (player.hasPermission("geometricmagic.transmutation.5")) { + transmutationCircleSize = 5; + } else if (player.hasPermission("geometricmagic.transmutation.3")) { + transmutationCircleSize = 3; + } else if (player.hasPermission("geometricmagic.transmutation.1")) { + transmutationCircleSize = 1; + } else { + transmutationCircleSize = 0; + player.sendMessage("You do not have permission to use this circle"); + } + + // Storage circle size permissions + int storageCircleSize = 1; + if (player.hasPermission("geometricmagic.storage.9")) { + storageCircleSize = 9; + } else if (player.hasPermission("geometricmagic.storage.7")) { + storageCircleSize = 7; + } else if (player.hasPermission("geometricmagic.storage.5")) { + storageCircleSize = 5; + } else if (player.hasPermission("geometricmagic.storage.3")) { + storageCircleSize = 3; + } else if (player.hasPermission("geometricmagic.storage.1")) { + storageCircleSize = 1; + } else { + storageCircleSize = 0; + player.sendMessage("You do not have permission to use this circle"); + } + + int circleSize = (transmutationCircleSize > storageCircleSize) ? transmutationCircleSize : storageCircleSize; + + // System.out.println("circleSize:" + circleSize); + + // transmute cool down + if (!player.hasPermission("geometricmagic.bypass.cooldown")) { + int coolDown = plugin.getConfig().getInt("transmutation.cooldown"); + if (mapCoolDowns.containsKey(player.getName() + " transmute circle")) { + long diff = (System.currentTimeMillis() - mapCoolDowns.get(player.getName() + " transmute circle")) / 1000; + if (diff < coolDown) { + // still cooling down + player.sendMessage(coolDown - diff + " seconds before you can do that again."); + return; + } + } + mapCoolDowns.put(player.getName() + " transmute circle", System.currentTimeMillis()); + } + + if (circleSize > 0) { + transmutationCircle(player, world, actBlock, transmutationCircleSize, storageCircleSize); + } + + // set circle + } else if (northBlock.getType() != Material.REDSTONE_WIRE && southBlock.getType() != Material.REDSTONE_WIRE && eastBlock.getType() != Material.REDSTONE_WIRE + && westBlock.getType() != Material.REDSTONE_WIRE && actBlock.getRelative(-3, 0, 0).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative(3, 0, 0).getType() == Material.REDSTONE_WIRE && actBlock.getRelative(0, 0, -3).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative(0, 0, 3).getType() == Material.REDSTONE_WIRE) { + + if (player.hasPermission("geometricmagic.set")) { + // set circle cool down + if (!player.hasPermission("geometricmagic.bypass.cooldown")) { + int coolDown = plugin.getConfig().getInt("setcircles.cooldown"); + if (mapCoolDowns.containsKey(player.getName() + " set circle")) { + long diff = (System.currentTimeMillis() - mapCoolDowns.get(player.getName() + " set circle")) / 1000; + if (diff < coolDown) { + // still cooling down + player.sendMessage(coolDown - diff + " seconds before you can do that again."); + return; + } + } + mapCoolDowns.put(player.getName() + " set circle", System.currentTimeMillis()); + } + + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + setCircleRemote(player, world, actBlock); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } else + player.sendMessage("You do not have permission to use this circle"); + + // no circle + } else { + return; + } + } + + public static void teleportationCircle(Player player, World world, Block actBlock) { + + // activation block in center + Location actPoint = actBlock.getLocation(); + + // init some variables + int na = 0, nb = 0, ea = 0, eb = 0, sa = 0, sb = 0, wa = 0, wb = 0, nc = 0, ec = 0, sc = 0, wc = 0; + + // set core blocks to air + actBlock.setType(Material.AIR); + actBlock.getRelative(1, 0, 0).setType(Material.AIR); + actBlock.getRelative(-1, 0, 0).setType(Material.AIR); + actBlock.getRelative(0, 0, 1).setType(Material.AIR); + actBlock.getRelative(0, 0, -1).setType(Material.AIR); + + // count and track all redstone blocks + Block curBlock = actBlock.getRelative(0, 0, -1); + while (curBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + na++; + curBlock = curBlock.getRelative(0, 0, -1); + } + Block fineBlock = curBlock; + while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + nb++; + fineBlock = fineBlock.getRelative(-1, 0, 0); + } + fineBlock = curBlock; + while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + nc++; + fineBlock = fineBlock.getRelative(1, 0, 0); + } + + curBlock = actBlock.getRelative(1, 0, 0); + while (curBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + ea++; + curBlock = curBlock.getRelative(1, 0, 0); + } + fineBlock = curBlock; + while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + eb++; + fineBlock = fineBlock.getRelative(0, 0, -1); + } + fineBlock = curBlock; + while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + ec++; + fineBlock = fineBlock.getRelative(0, 0, 1); + } + + curBlock = actBlock.getRelative(0, 0, 1); + while (curBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + sa++; + curBlock = curBlock.getRelative(0, 0, 1); + } + fineBlock = curBlock; + while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + sb++; + fineBlock = fineBlock.getRelative(1, 0, 0); + } + fineBlock = curBlock; + while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + sc++; + fineBlock = fineBlock.getRelative(-1, 0, 0); + } + + curBlock = actBlock.getRelative(-1, 0, 0); + while (curBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + wa++; + curBlock = curBlock.getRelative(-1, 0, 0); + } + fineBlock = curBlock; + while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + wb++; + fineBlock = fineBlock.getRelative(0, 0, 1); + } + fineBlock = curBlock; + while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + wc++; + fineBlock = fineBlock.getRelative(0, 0, -1); + } + + // set all redstone to air + curBlock = actBlock.getRelative(0, 0, -1); + for (int c = 0; c < na; c++) { + curBlock = curBlock.getRelative(0, 0, -1); + curBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < nb; c++) { + fineBlock = fineBlock.getRelative(-1, 0, 0); + fineBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < nc; c++) { + fineBlock = fineBlock.getRelative(1, 0, 0); + fineBlock.setType(Material.AIR); + } + + curBlock = actBlock.getRelative(1, 0, 0); + for (int c = 0; c < ea; c++) { + curBlock = curBlock.getRelative(1, 0, 0); + curBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < eb; c++) { + fineBlock = fineBlock.getRelative(0, 0, -1); + fineBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < ec; c++) { + fineBlock = fineBlock.getRelative(0, 0, 1); + fineBlock.setType(Material.AIR); + } + + curBlock = actBlock.getRelative(0, 0, 1); + for (int c = 0; c < sa; c++) { + curBlock = curBlock.getRelative(0, 0, 1); + curBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < sb; c++) { + fineBlock = fineBlock.getRelative(1, 0, 0); + fineBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < sc; c++) { + fineBlock = fineBlock.getRelative(-1, 0, 0); + fineBlock.setType(Material.AIR); + } + + curBlock = actBlock.getRelative(-1, 0, 0); + for (int c = 0; c < wa; c++) { + curBlock = curBlock.getRelative(-1, 0, 0); + curBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < wb; c++) { + fineBlock = fineBlock.getRelative(0, 0, 1); + fineBlock.setType(Material.AIR); + } + fineBlock = curBlock; + for (int c = 0; c < wc; c++) { + fineBlock = fineBlock.getRelative(0, 0, -1); + fineBlock.setType(Material.AIR); + } + + // find out teleport location and modify it + + // north negative z + // south positive z + // east positive x + // west negative x + int z = ((sa * 100 + sb) - (na * 100 + nb)); + int x = ((ea * 100 + eb) - (wa * 100 + wb)); + int y = nc + ec + sc + wc; + + double actPointX = actPoint.getX(); + double actPointZ = actPoint.getZ(); + + Location teleLoc = actPoint.add(x, y, z); + + float yaw = player.getLocation().getYaw(); + float pitch = player.getLocation().getPitch(); + + teleLoc.setYaw(yaw); + teleLoc.setPitch(pitch); + + double distance = Math.sqrt(Math.pow(teleLoc.getX() - actPointX, 2) + Math.pow(teleLoc.getZ() - actPointZ, 2)); + + double mathRandX = philosopherStoneModifier(player) * distance / 10 * Math.random(); + double mathRandZ = philosopherStoneModifier(player) * distance / 10 * Math.random(); + + double randX = (teleLoc.getX() - (0.5 * mathRandX)) + (mathRandX); + double randZ = (teleLoc.getZ() - (0.5 * mathRandZ)) + (mathRandZ); + + teleLoc.setX(randX); + teleLoc.setZ(randZ); + + // wait for chunk to be loaded before teleporting player + //while (teleLoc.getWorld().getChunkAt(teleLoc).isLoaded() == false) { + // teleLoc.getWorld().getChunkAt(teleLoc).load(true); + //} + // hopefully a bit more efficient + Chunk chunk = teleLoc.getChunk(); + while(!chunk.isLoaded() || !chunk.load(true)); + + // teleport player + player.teleport(teleLoc); + + ItemStack redstonePile = new ItemStack(331, 5 + na + nb + nc + sa + sb + sc + ea + eb + ec + wa + wb + wc); + + teleLoc.getWorld().dropItem(teleLoc, redstonePile); + + actBlock.getWorld().strikeLightningEffect(actBlock.getLocation()); + actBlock.getWorld().strikeLightningEffect(teleLoc); + + return; + } + + public static void microCircle(Player player, World world, Block actBlock) { + if (getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + Economy econ = GeometricMagic.getEconomy(); + + // Tell the player how much money they have + player.sendMessage("You have " + econ.format(getBalance(player))); + } else if (getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + // Tell the player how many levels they have + player.sendMessage("Your experience level is " + player.getLevel()); + } + + // Tell player when they can use a set circle + int coolDown = plugin.getConfig().getInt("setcircles.cooldown"); + if (mapCoolDowns.containsKey(player.getName() + " set circle")) { + long diff = (System.currentTimeMillis() - mapCoolDowns.get(player.getName() + " set circle")) / 1000; + if (diff < coolDown) { + // still cooling down + player.sendMessage(coolDown - diff + " seconds before you can use a set circle."); + } else { + // off cooldown + player.sendMessage("Your set circle is ready to use."); + } + } else { + // off cooldown + player.sendMessage("Your set circle is ready to use."); + } + + // Tell player when they can use a transmute circle + coolDown = plugin.getConfig().getInt("transmutation.cooldown"); + if (mapCoolDowns.containsKey(player.getName() + " transmute circle")) { + long diff = (System.currentTimeMillis() - mapCoolDowns.get(player.getName() + " transmute circle")) / 1000; + if (diff < coolDown) { + // still cooling down + player.sendMessage(coolDown - diff + " seconds before you can use a transmutation circle."); + } else { + // off cooldown + player.sendMessage("Your transmutation circle is ready to use."); + } + } else { + // off cooldown + player.sendMessage("Your transmutation circle is ready to use."); + } + + List entitiesList = player.getNearbyEntities(100, 32, 100); + int limitCount = plugin.getConfig().getInt("setcircles.limitarrows"); + + for (int i = 0; i < entitiesList.size() && limitCount != 0; i++) { + if (entitiesList.get(i) instanceof Arrow) { + Arrow shotArrow = (Arrow) entitiesList.get(i); + if (shotArrow.getLocation().getBlock().getType() == Material.REDSTONE_WIRE) { + limitCount--; + Block newActPoint = shotArrow.getLocation().getBlock(); + Player newPlayer = (Player) shotArrow.getShooter(); + circleChooser(newPlayer, world, newActPoint); + } + } + } + } + + public static void transmutationCircle(Player player, World world, Block actBlock, int transmutationCircleSize, int storageCircleSize) { + int halfWidth = 0; + int fullWidth = 0; + Location startLoc = actBlock.getLocation(); + Location endLoc = actBlock.getLocation(); + Location circleStart = actBlock.getLocation(); + Location circleEnd = actBlock.getLocation(); + Material fromType = actBlock.getType(); + Material toType = actBlock.getType(); + boolean lightning = false; + if (actBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE && actBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + halfWidth = 0; + while (actBlock.getRelative(0, 0, -1 * halfWidth).getType() == Material.REDSTONE_WIRE) { + halfWidth++; + } + fullWidth = (halfWidth * 2) - 1; + int dimensionOfEffect = (fullWidth - 2) * (fullWidth - 2); + if (actBlock.getRelative((fullWidth - 1), 0, 0).getType() == Material.REDSTONE_WIRE) { + // east + if (actBlock.getRelative((halfWidth - 1), 0, halfWidth).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative((halfWidth - 1), 0, (-1 * halfWidth)).getType() == Material.REDSTONE_WIRE) { + if (fullWidth - 2 > transmutationCircleSize) { + return; + } + Block fromBlock = actBlock.getLocation().add(halfWidth - 1, 0, -1 * (halfWidth + 1)).getBlock(); + Block toBlock = actBlock.getLocation().add(halfWidth - 1, 0, halfWidth + 1).getBlock(); + fromType = fromBlock.getType(); + toType = toBlock.getType(); + byte fromData = fromBlock.getData(); + byte toData = toBlock.getData(); + startLoc = actBlock.getLocation().add(fullWidth, 0, -1 * dimensionOfEffect / 2); + // System.out.println(startLoc); + endLoc = actBlock.getLocation().add(fullWidth + dimensionOfEffect - 1, dimensionOfEffect - 1, dimensionOfEffect / 2 - 1); + // System.out.println(endLoc); + circleStart = actBlock.getLocation().add(1, 0, -1 * (halfWidth - 2)); + // System.out.println(circleStart); + circleEnd = actBlock.getLocation().add(fullWidth - 2, fullWidth - 3, halfWidth - 2); + // System.out.println(circleEnd); + alchemyCheck(fromType, fromData, toType, toData, circleStart, circleEnd, startLoc, endLoc, player, fullWidth - 2); + lightning = true; + } + // Storage circle + else { + if (fullWidth - 2 > storageCircleSize) { + return; + } + startLoc = actBlock.getLocation().add(1, 0, (-1 * (halfWidth - 2))); + endLoc = actBlock.getLocation().add((fullWidth - 2), (fullWidth - 3), (halfWidth - 2)); + storageCircle(startLoc, endLoc, player, (fullWidth - 2)); + lightning = true; + } + } else if (actBlock.getRelative(-1 * (fullWidth - 1), 0, 0).getType() == Material.REDSTONE_WIRE) { + // west + // System.out.println("transmutationCircle west"); + if (actBlock.getRelative((-1 * (halfWidth - 1)), 0, halfWidth).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative((-1 * (halfWidth - 1)), 0, (-1 * halfWidth)).getType() == Material.REDSTONE_WIRE) { + if (fullWidth - 2 > transmutationCircleSize) { + return; + } + Block fromBlock = actBlock.getLocation().add(-1 * (halfWidth - 1), 0, halfWidth + 1).getBlock(); + Block toBlock = actBlock.getLocation().add((-1) * (halfWidth - 1), 0, (-1) * (halfWidth + 1)).getBlock(); + fromType = fromBlock.getType(); + toType = toBlock.getType(); + byte fromData = fromBlock.getData(); + byte toData = toBlock.getData(); + startLoc = actBlock.getLocation().add(-1 * fullWidth, 0, dimensionOfEffect / 2); + endLoc = actBlock.getLocation().add(-1 * (fullWidth + dimensionOfEffect) + 1, dimensionOfEffect - 1, -1 * dimensionOfEffect / 2 + 1); + circleStart = actBlock.getLocation().add(-1, 0, (halfWidth - 2)); + circleEnd = actBlock.getLocation().add(-1 * (fullWidth - 2), fullWidth - 3, -1 * (halfWidth - 2)); + alchemyCheck(fromType, fromData, toType, toData, circleStart, circleEnd, startLoc, endLoc, player, fullWidth - 2); + lightning = true; + } + // Storage circle + else { + if (fullWidth - 2 > storageCircleSize) { + return; + } + startLoc = actBlock.getLocation().add(-1, 0, (halfWidth - 2)); + endLoc = actBlock.getLocation().add((-1 * (fullWidth - 2)), (fullWidth - 3), (-1 * (halfWidth - 2))); + storageCircle(startLoc, endLoc, player, (fullWidth - 2)); + lightning = true; + } + } + } else if (actBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE && actBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + halfWidth = 0; + while (actBlock.getRelative(halfWidth, 0, 0).getType() == Material.REDSTONE_WIRE) { + halfWidth++; + } + fullWidth = (halfWidth * 2) - 1; + // System.out + // .println("half is " + halfWidth + " full is " + fullWidth); + int dimensionOfEffect = (fullWidth - 2) * (fullWidth - 2); + if (actBlock.getRelative(0, 0, -1 * (fullWidth - 1)).getType() == Material.REDSTONE_WIRE) { + // north + // System.out.println("transmutationCircle north"); + if (actBlock.getRelative(halfWidth, 0, (-1 * (halfWidth - 1))).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative((-1 * halfWidth), 0, (-1 * (halfWidth - 1))).getType() == Material.REDSTONE_WIRE) { + if (fullWidth - 2 > transmutationCircleSize) { + return; + } + Block fromBlock = actBlock.getLocation().add(-1 * (halfWidth + 1), 0, -1 * (halfWidth - 1)).getBlock(); + Block toBlock = actBlock.getLocation().add(halfWidth + 1, 0, -1 * (halfWidth - 1)).getBlock(); + fromType = fromBlock.getType(); + toType = toBlock.getType(); + byte fromData = fromBlock.getData(); + byte toData = toBlock.getData(); + startLoc = actBlock.getLocation().add(-1 * dimensionOfEffect / 2, 0, -1 * fullWidth); + endLoc = actBlock.getLocation().add(dimensionOfEffect / 2 - 1, dimensionOfEffect - 1, -1 * (dimensionOfEffect + fullWidth) + 1); + circleStart = actBlock.getLocation().add(-1 * (halfWidth - 2), 0, -1); + circleEnd = actBlock.getLocation().add((halfWidth - 2), fullWidth - 3, -1 * (fullWidth - 2)); + alchemyCheck(fromType, fromData, toType, toData, circleStart, circleEnd, startLoc, endLoc, player, fullWidth - 2); + lightning = true; + } + // Storage circle + else { + if (fullWidth - 2 > storageCircleSize) { + return; + } + startLoc = actBlock.getLocation().add((halfWidth - 2), 0, -1); + endLoc = actBlock.getLocation().add((halfWidth - 2), (fullWidth - 3), (-1 * (fullWidth - 2))); + storageCircle(startLoc, endLoc, player, (fullWidth - 2)); + lightning = true; + } + } else if (actBlock.getRelative(0, 0, (fullWidth - 1)).getType() == Material.REDSTONE_WIRE) { + // south + // System.out.println("transmutationCircle south"); + if (actBlock.getRelative(halfWidth, 0, (halfWidth -1)).getType() == Material.REDSTONE_WIRE + && actBlock.getRelative((-1 * halfWidth), 0, (halfWidth -1)).getType() == Material.REDSTONE_WIRE) { + if (fullWidth - 2 > transmutationCircleSize) { + return; + } + Block fromBlock = actBlock.getLocation().add(halfWidth + 1, 0, halfWidth - 1).getBlock(); + Block toBlock = actBlock.getLocation().add(-1 * (halfWidth + 1), 0, halfWidth - 1).getBlock(); + fromType = fromBlock.getType(); + toType = toBlock.getType(); + byte fromData = fromBlock.getData(); + byte toData = toBlock.getData(); + startLoc = actBlock.getLocation().add(dimensionOfEffect / 2, 0, fullWidth); + endLoc = actBlock.getLocation().add(-1 * dimensionOfEffect / 2 + 1, dimensionOfEffect - 1, fullWidth + dimensionOfEffect - 1); + circleStart = actBlock.getLocation().add(halfWidth - 2, 0, 1); + circleEnd = actBlock.getLocation().add(-1 * (halfWidth - 2), fullWidth - 3, (fullWidth - 2)); + alchemyCheck(fromType, fromData, toType, toData, circleStart, circleEnd, startLoc, endLoc, player, fullWidth - 2); + lightning = true; + } + // Storage circle + else { + if (fullWidth - 2 > storageCircleSize) { + return; + } + startLoc = actBlock.getLocation().add((halfWidth - 2), 0, 1); + endLoc = actBlock.getLocation().add((-1 * (halfWidth - 2)), (fullWidth - 3), (fullWidth - 2)); + storageCircle(startLoc, endLoc, player, (fullWidth - 2)); + lightning = true; + } + } + } + if (lightning) + actBlock.getWorld().strikeLightningEffect(actBlock.getLocation()); + } + + public static void setCircleRemote(Player player, World world, Block actBlock) { + Boolean remote = false; + Block effectBlock = actBlock; + + List entitiesList = player.getNearbyEntities(100, 32, 100); + int limit = plugin.getConfig().getInt("setcircles.limitarrows"); + int limitCount = limit; + + for (int i = 0; i < entitiesList.size() && limitCount != 0; i++) { + if (entitiesList.get(i) instanceof Arrow) { + Arrow shotArrow = (Arrow) entitiesList.get(i); + if (shotArrow.getLocation().getBlock().getX() == actBlock.getLocation().getBlock().getX() && shotArrow.getLocation().getBlock().getZ() == actBlock.getLocation().getBlock().getZ()) { + limitCount--; + remote = true; + entitiesList.remove(i); + } + } + } + + limitCount = limit; + + if (remote) { + for (int i = 0; i < entitiesList.size() && limitCount != 0; i++) { + if (entitiesList.get(i) instanceof Arrow) { + limitCount--; + Arrow shotArrow = (Arrow) entitiesList.get(i); + effectBlock = shotArrow.getLocation().getBlock(); + setCircle(player, world, actBlock, effectBlock); + } + } + } else + setCircle(player, world, actBlock, effectBlock); + } + + public static void setCircle(Player player, World world, Block actBlock, Block effectBlock) { + Block northSin = actBlock.getRelative(0, 0, -3); + Block southSin = actBlock.getRelative(0, 0, 3); + Block eastSin = actBlock.getRelative(3, 0, 0); + Block westSin = actBlock.getRelative(-3, 0, 0); + int n = 0; + int s = 0; + int e = 0; + int w = 0; + int[] intArray = new int[4]; + if (northSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) + n++; + if (northSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) + n++; + if (northSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) + n++; + if (northSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) + n++; + intArray[0] = n; + if (southSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) + s++; + if (southSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) + s++; + if (southSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) + s++; + if (southSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) + s++; + intArray[1] = s; + if (eastSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) + e++; + if (eastSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) + e++; + if (eastSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) + e++; + if (eastSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) + e++; + intArray[2] = e; + if (westSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) + w++; + if (westSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) + w++; + if (westSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) + w++; + if (westSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) + w++; + intArray[3] = w; + Arrays.sort(intArray); + String arrayString = Arrays.toString(intArray); + try { + setCircleEffects(player, world, actBlock, effectBlock, arrayString); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + public static void setCircleEffects(Player player, World world, Block actBlock, Block effectBlock, String arrayString) throws IOException { + Location effectBlockLocation = effectBlock.getLocation(); + int cost = 0; + if (!hasLearnedCircle(player, arrayString)) { + if (learnCircle(player, arrayString, actBlock)) { + player.sendMessage("You have successfully learned the circle " + arrayString); + return; + } + } + if (arrayString.equals("0")) + return; + if (arrayString.equals("[1, 1, 1, 1]") && player.hasPermission("geometricmagic.set.1111")) { + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + + cost = plugin.getConfig().getInt("setcircles.1222.cost"); + if (cost > 20) + cost = 20; + + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + + int itemID = plugin.getConfig().getInt("setcircles.1111.item"); + ItemStack item = new ItemStack(itemID); + effectBlock.getWorld().dropItem(effectBlockLocation, item); + + } else { + player.sendMessage("You feel so hungry..."); + return; + } + } + else if (arrayString.equals("[1, 1, 3, 3]") && player.hasPermission("geometricmagic.set.1133")) { + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + } + + int count = 0; + List repairEntities = player.getNearbyEntities(9, 10, 9); + for (int i = 0; i < repairEntities.size(); i++) { + if (repairEntities.get(i) instanceof Item) { + Item droppedItem = (Item) repairEntities.get(i); + + // Item data value + int itemCode = droppedItem.getItemStack().getTypeId(); + + // Enchantments + Map effects = droppedItem.getItemStack().getEnchantments(); + + // Get cost + if ((256 <= itemCode && itemCode <= 258) || (267 <= itemCode && itemCode <= 279) || (283 <= itemCode && itemCode <= 286) || (290 <= itemCode && itemCode <= 294) + || (298 <= itemCode && itemCode <= 317) || itemCode == 259 || itemCode == 346 || itemCode == 359 || itemCode == 261) { + if ((256 <= itemCode && itemCode <= 258) || itemCode == 267 || itemCode == 292) + cost = droppedItem.getItemStack().getDurability(); + if ((268 <= itemCode && itemCode <= 271) || itemCode == 290) + cost = droppedItem.getItemStack().getDurability(); + if ((272 <= itemCode && itemCode <= 275) || itemCode == 291) + cost = droppedItem.getItemStack().getDurability(); + if ((276 <= itemCode && itemCode <= 279) || itemCode == 293) + cost = droppedItem.getItemStack().getDurability(); + if ((283 <= itemCode && itemCode <= 286) || itemCode == 294) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 298) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 299) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 300) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 301) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 306) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 307) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 308) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 309) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 310) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 311) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 312) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 313) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 314) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 315) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 316) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 317) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 259) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 346) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 359) + cost = droppedItem.getItemStack().getDurability(); + if (itemCode == 261) + cost = droppedItem.getItemStack().getDurability(); + cost = cost / 50; + + // Make sure cost is not more than 20 + if (cost > 20) + cost = 20; + + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + ItemStack newItem = new ItemStack(itemCode, 1); + + // enchant the item + newItem.addEnchantments(effects); + + droppedItem.remove(); + effectBlock.getWorld().dropItem(effectBlockLocation, newItem); + count++; + } else { + player.sendMessage("You feel so hungry..."); + if (count > 0) + effectBlock.getWorld().strikeLightningEffect(effectBlockLocation); + return; + } + } + } + } + } else if (arrayString.equals("[1, 2, 2, 2]") && player.hasPermission("geometricmagic.set.1222")) { + + cost = plugin.getConfig().getInt("setcircles.1222.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + + ItemStack oneRedstone = new ItemStack(331, 1); + Item redStack = effectBlock.getWorld().dropItem(effectBlockLocation, oneRedstone); + List entityList = redStack.getNearbyEntities(5, 10, 5); + for (int i = 0; i < entityList.size(); i++) { + if (entityList.get(i) instanceof Item) { + Item droppedItem = (Item) entityList.get(i); + + // Skip items because they don't have values + if(droppedItem.getItemStack().getTypeId() > 255) { + player.sendMessage("You can't use items, only blocks"); + continue; + } + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(droppedItem.getLocation(), player)) { + // player.sendMessage("You don't have permission to do that there."); + redStack.remove(); + return; + } + + int valueArray = getBlockValue(plugin, droppedItem.getItemStack().getTypeId(), droppedItem.getItemStack().getData().getData()); + + int pay = (valueArray * droppedItem.getItemStack().getAmount()); + + if (getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + Economy econ = GeometricMagic.getEconomy(); + if (pay > 0) { + econ.depositPlayer(player.getName(), pay); + player.sendMessage("Deposited " + pay + " " + econ.currencyNamePlural() + " for " + droppedItem.getItemStack().getType().name().toLowerCase().replace('_', ' ')); + droppedItem.remove(); + } else if (pay < 0) { + econ.withdrawPlayer(player.getName(), pay * -1); + player.sendMessage("Withdrew " + pay + " " + econ.currencyNamePlural() + " for " + droppedItem.getItemStack().getType().name().toLowerCase().replace('_', ' ')); + droppedItem.remove(); + } + } else if (getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + player.setLevel((valueArray * droppedItem.getItemStack().getAmount()) + player.getLevel()); + droppedItem.remove(); + } + + /* + * player.setLevel((valueArray[droppedItem.getItemStack() + * .getTypeId()] * droppedItem.getItemStack() + * .getAmount()) + player.getLevel()); + */ + } + } + redStack.remove(); + } else { + player.sendMessage("You feel so hungry..."); + return; + } + } else if (arrayString.equals("[1, 2, 3, 3]") && player.hasPermission("geometricmagic.set.1233")) { + + cost = plugin.getConfig().getInt("setcircles.1233.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + ItemStack onePortal = new ItemStack(90, 1); + int fires = 0; + List entityList = player.getNearbyEntities(10, 10, 10); + for (int i = 0; i < entityList.size(); i++) { + if (entityList.get(i) instanceof Item) { + Item sacrifice = (Item) entityList.get(i); + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(sacrifice.getLocation(), player)) { + // player.sendMessage("You don't have permission to do that there."); + return; + } + + if (sacrifice.getItemStack().getType() == Material.FIRE) { + fires += sacrifice.getItemStack().getAmount(); + sacrifice.remove(); + } + } + } + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (fires >= 64) { + fires -= 64; + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + effectBlock.getWorld().dropItem(effectBlockLocation, onePortal); + } + } else { + player.sendMessage("You feel so hungry..."); + } + ItemStack diamondStack = new ItemStack(264, fires); + effectBlock.getWorld().dropItem(effectBlockLocation, diamondStack); + } else if (arrayString.equals("[1, 2, 3, 4]") && player.hasPermission("geometricmagic.set.1234")) { + + cost = plugin.getConfig().getInt("setcircles.1234.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + player.sendMessage(ChatColor.GREEN + "The four elements, like man alone, are weak. But together they form the strong fifth element: boron -Brother Silence"); + int amount = plugin.getConfig().getInt("setcircles.1234.amount"); + ItemStack oneRedstone = new ItemStack(331, amount); + + effectBlock.getWorld().dropItem(effectBlockLocation, oneRedstone); + + } else { + player.sendMessage("You feel so hungry..."); + return; } - inputFile.close(); - //System.out.println("isCircle not clicked redstone"); - setCircleEffects(player, player.getWorld(), player.getLocation().getBlock(), actBlock, circle); - } - else - return; - } - - public static void circleChooser(Player player, World world, Block actBlock) { - //System.out.println("circleChooser"); - Block northBlock = actBlock.getRelative(0, 0, -1); - Block southBlock = actBlock.getRelative(0, 0, 1); - Block eastBlock = actBlock.getRelative(1, 0, 0); - Block westBlock = actBlock.getRelative(-1, 0, 0); - if (northBlock.getType() == Material.REDSTONE_WIRE - && southBlock.getType() == Material.REDSTONE_WIRE - && eastBlock.getType() == Material.REDSTONE_WIRE - && westBlock.getType() == Material.REDSTONE_WIRE) { - if(player.hasPermission("circle.teleportation")) { - //System.out.println("teleportation"); - teleportationCircle(player, world, actBlock); + } else if (arrayString.equals("[2, 2, 2, 3]") && player.hasPermission("geometricmagic.set.2223")) { + + cost = plugin.getConfig().getInt("setcircles.2223.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; } - else - player.sendMessage("You do not have permission to use this circle"); - } - else if (northBlock.getType() != Material.REDSTONE_WIRE - && southBlock.getType() != Material.REDSTONE_WIRE - && eastBlock.getType() != Material.REDSTONE_WIRE - && westBlock.getType() != Material.REDSTONE_WIRE - && actBlock.getRelative(-3, 0, 0).getType() != Material.REDSTONE_WIRE - && actBlock.getRelative(3, 0, 0).getType() != Material.REDSTONE_WIRE - && actBlock.getRelative(0, 0, -3).getType() != Material.REDSTONE_WIRE - && actBlock.getRelative(0, 0, 3).getType() != Material.REDSTONE_WIRE) { - if(player.hasPermission("circle.micro")){ - //System.out.println("micro"); - microCircle(player, world, actBlock); + ItemStack oneRedstone = new ItemStack(331, 1); + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + Item redStack = effectBlock.getWorld().dropItem(effectBlockLocation, oneRedstone); + int size = setCircleSize(actBlock); + List entityList = redStack.getNearbyEntities(size + 5, 128, size + 5); + + for (int i = 0; i < entityList.size(); i++) { + if (entityList.get(i) instanceof Player) { + HumanEntity victim = (HumanEntity) entityList.get(i); + Location victimLocation = victim.getLocation(); + + if (!victim.equals(player)) { + victim.getWorld().strikeLightningEffect(victimLocation); + if (victim.getInventory().contains(Material.FIRE)) { + for (int k = 0; k < player.getInventory().getSize(); k++) { + if (player.getInventory().getItem(i).getType() == Material.FIRE) { + // System.out.println("removed a fire"); + int amount = player.getInventory().getItem(k).getAmount(); + player.getInventory().getItem(k).setAmount(amount - 1); + if (amount - 1 <= 0) { + player.getInventory().clear(k); + } + } + } + } else + victim.damage(20); + if (victim.isDead()) { + ItemStack oneFire = new ItemStack(51, 1); + victim.getWorld().dropItem(actBlock.getLocation(), oneFire); + } + } + } + if (entityList.get(i) instanceof Villager) { + Villager victim = (Villager) entityList.get(i); + victim.getWorld().strikeLightningEffect(victim.getLocation()); + victim.damage(20); + if (victim.isDead()) { + ItemStack oneFire = new ItemStack(51, 1); + victim.getWorld().dropItem(actBlock.getLocation(), oneFire); + } + } + } + redStack.remove(); + } else { + player.sendMessage("You feel so hungry..."); + return; } - else - player.sendMessage("You do not have permission to use this circle"); - } - else if ((northBlock.getType() == Material.REDSTONE_WIRE - && southBlock.getType() == Material.REDSTONE_WIRE - && eastBlock.getType() != Material.REDSTONE_WIRE && westBlock - .getType() != Material.REDSTONE_WIRE) - || (northBlock.getType() != Material.REDSTONE_WIRE - && southBlock.getType() != Material.REDSTONE_WIRE - && eastBlock.getType() == Material.REDSTONE_WIRE && westBlock - .getType() == Material.REDSTONE_WIRE)) { - if(player.hasPermission("circle.transmutation")){ - //System.out.println("transmutation"); - transmutationCircle(player, world, actBlock); + } else if (arrayString.equals("[2, 2, 2, 4]") && player.hasPermission("geometricmagic.set.2224")) { + + cost = plugin.getConfig().getInt("setcircles.2224.cost"); + if (cost > 20) + cost = 20; + + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + Location spawnLoc = effectBlockLocation; + spawnLoc.add(0.5, 1, 0.5); + effectBlock.getWorld().spawn(spawnLoc, Enderman.class); + } else { + player.sendMessage("You feel so hungry..."); + return; } - else - player.sendMessage("You do not have permission to use this circle"); - } - else if (northBlock.getType() != Material.REDSTONE_WIRE - && southBlock.getType() != Material.REDSTONE_WIRE - && eastBlock.getType() != Material.REDSTONE_WIRE - && westBlock.getType() != Material.REDSTONE_WIRE - && actBlock.getRelative(-3, 0, 0).getType() == Material.REDSTONE_WIRE - && actBlock.getRelative(3, 0, 0).getType() == Material.REDSTONE_WIRE - && actBlock.getRelative(0, 0, -3).getType() == Material.REDSTONE_WIRE - && actBlock.getRelative(0, 0, 3).getType() == Material.REDSTONE_WIRE) { - if(player.hasPermission("circle.set")){ - //System.out.println("set"); - setCircleRemote(player, world, actBlock); + } else if (arrayString.equals("[2, 2, 4, 4]") && player.hasPermission("geometricmagic.set.2244")) { + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; } - else - player.sendMessage("You do not have permission to use this circle"); - } - else - return; - } - - public static void teleportationCircle(Player player, World world, Block actBlock) { - Location actPoint = actBlock.getLocation(); - int na = 0, nb = 0, ea = 0, eb = 0, sa = 0, sb = 0, wa = 0, wb = 0, nc = 0, ec = 0, sc = 0, wc = 0; - actBlock.setType(Material.AIR); - actBlock.getRelative(1, 0, 0).setType(Material.AIR); - actBlock.getRelative(-1, 0, 0).setType(Material.AIR); - actBlock.getRelative(0, 0, 1).setType(Material.AIR); - actBlock.getRelative(0, 0, -1).setType(Material.AIR); - Block curBlock = actBlock.getRelative(0, 0, -1); + + cost = plugin.getConfig().getInt("setcircles.2244.cost"); + if (cost > 20) + cost = 20; + + Location actPoint = effectBlockLocation; + int na = 0, nb = 0, ea = 0, eb = 0, sa = 0, sb = 0, wa = 0, wb = 0; + Block curBlock = effectBlock.getRelative(0, 0, -1); while (curBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { na++; curBlock = curBlock.getRelative(0, 0, -1); - curBlock.setType(Material.AIR); } Block fineBlock = curBlock; while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { nb++; fineBlock = fineBlock.getRelative(-1, 0, 0); - fineBlock.setType(Material.AIR); - } - fineBlock = curBlock; - while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { - nc++; - fineBlock = fineBlock.getRelative(1, 0, 0); - fineBlock.setType(Material.AIR); } - curBlock = actBlock.getRelative(1, 0, 0); + curBlock = effectBlock.getRelative(1, 0, 0); while (curBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { ea++; curBlock = curBlock.getRelative(1, 0, 0); - curBlock.setType(Material.AIR); } fineBlock = curBlock; while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { eb++; fineBlock = fineBlock.getRelative(0, 0, -1); - fineBlock.setType(Material.AIR); - } - fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { - ec++; - fineBlock = fineBlock.getRelative(0, 0, 1); - fineBlock.setType(Material.AIR); } - curBlock = actBlock.getRelative(0, 0, 1); + curBlock = effectBlock.getRelative(0, 0, 1); while (curBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { sa++; curBlock = curBlock.getRelative(0, 0, 1); - curBlock.setType(Material.AIR); } fineBlock = curBlock; while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { sb++; fineBlock = fineBlock.getRelative(1, 0, 0); - fineBlock.setType(Material.AIR); - } - fineBlock = curBlock; - while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { - sc++; - fineBlock = fineBlock.getRelative(-1, 0, 0); - fineBlock.setType(Material.AIR); } - curBlock = actBlock.getRelative(-1, 0, 0); + curBlock = effectBlock.getRelative(-1, 0, 0); while (curBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { wa++; curBlock = curBlock.getRelative(-1, 0, 0); - curBlock.setType(Material.AIR); } fineBlock = curBlock; while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { wb++; fineBlock = fineBlock.getRelative(0, 0, 1); - fineBlock.setType(Material.AIR); - } - fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { - wc++; - fineBlock = fineBlock.getRelative(0, 0, -1); - fineBlock.setType(Material.AIR); } // north negative z, south positive z, east positive x, west // negative x int z = ((sa * 100 + sb) - (na * 100 + nb)); int x = ((ea * 100 + eb) - (wa * 100 + wb)); - int y = nc + ec + sc + wc; double actPointX = actPoint.getX(); double actPointZ = actPoint.getZ(); - Location teleLoc = actPoint.add(x, y, z); - float yaw = player.getLocation().getYaw(); - float pitch = player.getLocation().getPitch(); - teleLoc.setYaw(yaw); - teleLoc.setPitch(pitch); + Location teleLoc = actPoint.add(x, 0, z); double distance = Math.sqrt(Math.pow(teleLoc.getX() - actPointX, 2) + Math.pow(teleLoc.getZ() - actPointZ, 2)); - double mathRandX = philosopherStoneModifier(player) * distance/10 * Math.random(); - double mathRandZ = philosopherStoneModifier(player) * distance/10 * Math.random(); - double randX = (teleLoc.getX() - (0.5 * mathRandX)) - + (mathRandX); - double randZ = (teleLoc.getZ() - (0.5 * mathRandZ)) - + (mathRandZ); + double mathRandX = philosopherStoneModifier(player) * distance / 10 * Math.random(); + double mathRandZ = philosopherStoneModifier(player) * distance / 10 * Math.random(); + double randX = (teleLoc.getX() - (0.5 * mathRandX)) + (mathRandX); + double randZ = (teleLoc.getZ() - (0.5 * mathRandZ)) + (mathRandZ); teleLoc.setX(randX); teleLoc.setZ(randZ); - while (teleLoc.getWorld().getChunkAt(teleLoc).isLoaded() == false){ + while (teleLoc.getWorld().getChunkAt(teleLoc).isLoaded() == false) { teleLoc.getWorld().getChunkAt(teleLoc).load(true); - } - player.teleport(teleLoc); - ItemStack redstonePile = new ItemStack(331, 5 + na + nb + nc + sa + sb + sc + ea + eb + ec + wa + wb + wc); - teleLoc.getWorld().dropItem(teleLoc, redstonePile); - actBlock.getWorld().strikeLightningEffect(actBlock.getLocation()); - actBlock.getWorld().strikeLightningEffect(teleLoc); + } + int highestBlock = teleLoc.getWorld().getHighestBlockYAt(teleLoc) + 1; + // System.out.println( mathRandX + " " + mathRandZ ); + player.sendMessage("Safe teleportation altitude is at " + highestBlock); return; - } - - public static void microCircle (Player player, World world, Block actBlock) { - // have it print to console what level is - player.sendMessage("Your experience level is " + player.getLevel()); - List entitiesList = player.getNearbyEntities(100, 10, 100); - for (int i = 0; i < entitiesList.size(); i++){ - if (entitiesList.get(i) instanceof Arrow){ - Arrow shotArrow = (Arrow) entitiesList.get(i); - if (shotArrow.getLocation().getBlock().getType() == Material.REDSTONE_WIRE){ - Block newActPoint = shotArrow.getLocation().getBlock(); - Player newPlayer = (Player) shotArrow.getShooter(); - circleChooser(newPlayer, world, newActPoint); - } - } + } else if (arrayString.equals("[2, 3, 3, 3]") && player.hasPermission("geometricmagic.set.2333")) { + + cost = plugin.getConfig().getInt("setcircles.2333.cost"); + if (cost > 20) + cost = 20; + + int size = setCircleSize(actBlock); + cost = cost + size / 2; + + // Make sure cost is not more than 20 + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; } - } - - public static void transmutationCircle (Player player, World world, Block actBlock){ - int halfWidth = 0; - int fullWidth = 0; - Location startLoc = actBlock.getLocation(); - Location endLoc = actBlock.getLocation(); - Location circleStart = actBlock.getLocation(); - Location circleEnd = actBlock.getLocation(); - Material fromType = actBlock.getType(); - Material toType = actBlock.getType(); - if (actBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE - && actBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { - halfWidth = 0; - while (actBlock.getRelative(0, 0, -1 * halfWidth).getType() == Material.REDSTONE_WIRE) { - halfWidth++; - } - fullWidth = (halfWidth * 2) - 1; - int dimensionOfEffect = (fullWidth - 2) * (fullWidth - 2); - if (actBlock.getRelative((fullWidth - 1), 0, 0).getType() == Material.REDSTONE_WIRE) { - //east - fromType = actBlock.getLocation().add( - halfWidth - 1, 0, -1 * (halfWidth + 1)).getBlock() - .getType(); - toType = actBlock.getLocation().add(halfWidth - 1, - 0, halfWidth + 1).getBlock().getType(); - startLoc = actBlock.getLocation().add(fullWidth, - 0, -1 * dimensionOfEffect / 2 + 1); - endLoc = actBlock.getLocation().add( - fullWidth + dimensionOfEffect - 1, dimensionOfEffect -1, - dimensionOfEffect / 2 - 1); - circleStart = actBlock.getLocation().add(1, 0, -1 * (halfWidth - 2)); - circleEnd = actBlock.getLocation().add(fullWidth - 2, fullWidth - 3, halfWidth -2); - alchemyCheck(fromType, toType, circleStart, circleEnd, startLoc, endLoc, player, fullWidth -2); - } else if (actBlock.getRelative(-1 * (fullWidth - 1), 0, 0) - .getType() == Material.REDSTONE_WIRE) { - //west - fromType = actBlock.getLocation().add( - -1 * (halfWidth - 1), 0, halfWidth + 1).getBlock() - .getType(); - toType = actBlock.getLocation().add( - (-1) * (halfWidth - 1), 0, (-1) * (halfWidth + 1)) - .getBlock().getType(); - startLoc = actBlock.getLocation().add( - -1 * fullWidth, 0, dimensionOfEffect / 2); - endLoc = actBlock.getLocation().add( - -1 * (fullWidth + dimensionOfEffect) + 1, - dimensionOfEffect - 1, -1 * dimensionOfEffect / 2 + 1); - circleStart = actBlock.getLocation().add(-1, 0, (halfWidth - 2)); - circleEnd = actBlock.getLocation().add(-1 * (fullWidth - 2), fullWidth - 3, -1 * (halfWidth - 2)); - alchemyCheck(fromType, toType, circleStart, circleEnd, startLoc, endLoc, player, fullWidth -2); - } - } else if (actBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE - && actBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { - halfWidth = 0; - while (actBlock.getRelative(halfWidth, 0, 0).getType() == Material.REDSTONE_WIRE) { - halfWidth++; - } - fullWidth = (halfWidth * 2) - 1; - //System.out.println("half is " + halfWidth + " full is " + fullWidth); - int dimensionOfEffect = (fullWidth - 2) * (fullWidth - 2); - if (actBlock.getRelative(0, 0, -1 * (fullWidth - 1)).getType() == Material.REDSTONE_WIRE) { - //north - //System.out.println("transmutationCircle north"); - fromType = actBlock.getLocation().add( - -1 * (halfWidth + 1), 0, -1 * (halfWidth - 1)) - .getBlock().getType(); - toType = actBlock.getLocation().add(halfWidth + 1, - 0, -1 * (halfWidth - 1)).getBlock().getType(); - startLoc = actBlock.getLocation().add( - -1 * dimensionOfEffect / 2, 0, -1 * fullWidth); - endLoc = actBlock.getLocation().add( - dimensionOfEffect / 2 - 1, dimensionOfEffect - 1, - -1 * (dimensionOfEffect + fullWidth) + 1); - circleStart = actBlock.getLocation().add(-1 * (halfWidth - 2), 0, -1); - circleEnd = actBlock.getLocation().add((halfWidth - 2), fullWidth - 3, -1 * (fullWidth - 2)); - alchemyCheck(fromType, toType, circleStart, circleEnd, startLoc, endLoc, player, fullWidth -2); - } else if (actBlock.getRelative(0, 0, (fullWidth - 1)) - .getType() == Material.REDSTONE_WIRE) { - //south - //System.out.println("transmutationCircle south"); - fromType = actBlock.getLocation().add( - halfWidth + 1, 0, halfWidth - 1).getBlock() - .getType(); - toType = actBlock.getLocation().add( - -1 * (halfWidth + 1), 0, halfWidth - 1).getBlock() - .getType(); - startLoc = actBlock.getLocation().add( - dimensionOfEffect / 2, 0, fullWidth); - endLoc = actBlock.getLocation().add( - -1 * dimensionOfEffect / 2 + 1, dimensionOfEffect - 1, - fullWidth + dimensionOfEffect - 1); - circleStart = actBlock.getLocation().add(halfWidth - 2, 0, 1); - circleEnd = actBlock.getLocation().add(-1 * (halfWidth - 2), fullWidth - 3, (fullWidth - 2)); - alchemyCheck(fromType, toType, circleStart, circleEnd, startLoc, endLoc, player, fullWidth -2); + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); } - } - actBlock.getWorld().strikeLightningEffect(actBlock.getLocation()); - } - - public static void setCircleRemote(Player player, World world, Block actBlock){ - Boolean remote = false; - Block effectBlock = actBlock; - List entitiesList = player.getNearbyEntities(242, 20, 242); - for (int i = 0; i < entitiesList.size(); i++){ - if (entitiesList.get(i) instanceof Arrow){ - Arrow shotArrow = (Arrow) entitiesList.get(i); - if (shotArrow.getLocation().getBlock().getX() == actBlock.getLocation().getBlock().getX() && shotArrow.getLocation().getBlock().getZ() == actBlock.getLocation().getBlock().getZ()){ - remote = true; - entitiesList.remove(i); - } + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(effectBlockLocation, player)) { + // player.sendMessage("You don't have permission to do that there."); + return; } + + Fireball fireball = effectBlockLocation.getWorld().spawn(effectBlockLocation, Fireball.class); + fireball.setIsIncendiary(false); + fireball.setYield(4 + size); + } else { + player.sendMessage("You feel so hungry..."); + return; } - if (remote){ - for (int i = 0; i < entitiesList.size(); i++){ - if (entitiesList.get(i) instanceof Arrow){ - Arrow shotArrow = (Arrow) entitiesList.get(i); - effectBlock = shotArrow.getLocation().getBlock(); - setCircle(player, world, actBlock, effectBlock); - } + } else if (arrayString.equals("[3, 3, 3, 4]") && player.hasPermission("geometricmagic.set.3334")) { + + cost = plugin.getConfig().getInt("setcircles.3334.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); } + + Integer circleSize = plugin.getConfig().getInt("setcircles.3334.size"); + + alchemyFiller(Material.AIR, (byte) 0, Material.FIRE, (byte) 0, effectBlock.getRelative((circleSize / 2) * -1, 0, (circleSize / 2) * -1).getLocation(), + effectBlock.getRelative(circleSize / 2, circleSize, circleSize / 2).getLocation(), player, false); + + } else { + player.sendMessage("You feel so hungry..."); + return; } - else - setCircle(player, world, actBlock, effectBlock); - } - - public static void setCircle(Player player, World world, Block actBlock, Block effectBlock){ - Block northSin = actBlock.getRelative(0, 0, -3); - Block southSin = actBlock.getRelative(0, 0, 3); - Block eastSin = actBlock.getRelative(3, 0, 0); - Block westSin = actBlock.getRelative(-3, 0, 0); - int n = 0; - int s = 0; - int e = 0; - int w = 0; - int[] intArray = new int[4]; - if (northSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) - n ++; - if (northSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) - n ++; - if (northSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) - n ++; - if (northSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) - n ++; - intArray[0] = n; - if (southSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) - s ++; - if (southSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) - s ++; - if (southSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) - s ++; - if (southSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) - s ++; - intArray[1] = s; - if (eastSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) - e ++; - if (eastSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) - e ++; - if (eastSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) - e ++; - if (eastSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) - e ++; - intArray[2] = e; - if (westSin.getRelative(BlockFace.NORTH).getType() == Material.REDSTONE_WIRE) - w ++; - if (westSin.getRelative(BlockFace.SOUTH).getType() == Material.REDSTONE_WIRE) - w ++; - if (westSin.getRelative(BlockFace.EAST).getType() == Material.REDSTONE_WIRE) - w ++; - if (westSin.getRelative(BlockFace.WEST).getType() == Material.REDSTONE_WIRE) - w ++; - intArray[3] = w; - Arrays.sort(intArray); - String arrayString = Arrays.toString(intArray); - try { - setCircleEffects(player, world, actBlock, effectBlock, arrayString); - } catch (IOException e1) { - e1.printStackTrace(); + } else if (arrayString.equals("[3, 3, 4, 4]") && player.hasPermission("geometricmagic.set.3344")) { + + cost = plugin.getConfig().getInt("setcircles.3344.cost"); + if (cost > 20) + cost = 20; + + int size = setCircleSize(actBlock); + cost = cost + size / 2; + + // Make sure cost is not more than 20 + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; } - } - - public static void setCircleEffects(Player player, World world, Block actBlock, Block effectBlock, String arrayString) throws IOException{ - int cost = 0; - if (!hasLearnedCircle(player, arrayString)){ - if (learnCircle(player, arrayString, actBlock)){ - player.sendMessage("You have successfully learned the circle " + arrayString); + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(effectBlockLocation, player)) { + // player.sendMessage("You don't have permission to do that there."); return; } + + Fireball fireball = effectBlockLocation.getWorld().spawn(effectBlockLocation, Fireball.class); + fireball.setIsIncendiary(true); + fireball.setYield(4 + size); + } else { + player.sendMessage("You feel so hungry..."); + return; } - if (arrayString.equals("0")) + } else if (arrayString.equals("[3, 4, 4, 4]") && player.hasPermission("geometricmagic.set.3444")) { + + cost = plugin.getConfig().getInt("setcircles.3444.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); return; - if (arrayString.equals("[1, 1, 3, 3]") && player.hasPermission("circle.set.1133")){ - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; - } - List repairEntities = player.getNearbyEntities(9, 10, 9); - for (int i = 0; i < repairEntities.size(); i++){ - if (repairEntities.get(i) instanceof Item){ - Item droppedItem = (Item) repairEntities.get(i); - if ( (256 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 258) || (267 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 279) || (283 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 286) || (290 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 294) || (298 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 317) || droppedItem.getItemStack().getTypeId() == 259 || droppedItem.getItemStack().getTypeId() == 346 || droppedItem.getItemStack().getTypeId() == 359 || droppedItem.getItemStack().getTypeId() == 261 ){ - if ((256 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 258) || droppedItem.getItemStack().getTypeId() == 267 || droppedItem.getItemStack().getTypeId() == 292 ) - cost = droppedItem.getItemStack().getDurability(); - if ( (268 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 271) || droppedItem.getItemStack().getTypeId() == 290) - cost = droppedItem.getItemStack().getDurability(); - if ( (272 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 275) || droppedItem.getItemStack().getTypeId() == 291) - cost = droppedItem.getItemStack().getDurability(); - if ( (276 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 279) || droppedItem.getItemStack().getTypeId() == 293) - cost = droppedItem.getItemStack().getDurability(); - if ( (283 <= droppedItem.getItemStack().getTypeId() && droppedItem.getItemStack().getTypeId() <= 286) || droppedItem.getItemStack().getTypeId() == 294) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 298) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 299) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 300) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 301) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 306) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 307) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 308) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 309) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 310) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 311) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 312) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 313) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 314) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 315) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 316) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 317) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 259) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 346) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 359) - cost = droppedItem.getItemStack().getDurability(); - if (droppedItem.getItemStack().getTypeId() == 261) - cost = droppedItem.getItemStack().getDurability(); - cost = cost / 50; - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - ItemStack newItem = new ItemStack(droppedItem.getItemStack().getTypeId(), 1); - droppedItem.remove(); - effectBlock.getWorld().dropItem(effectBlock.getLocation(), newItem); - } else - return; - } - } - } } - else if (arrayString.equals("[1, 2, 2, 2]") && player.hasPermission("circle.set.1222")){ - cost = 1; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; + if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + try { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + humanTransmutation(player); + } catch (IOException e1) { + e1.printStackTrace(); } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - ItemStack oneRedstone = new ItemStack(331, 1); - Item redStack = effectBlock.getWorld().dropItem(effectBlock.getLocation(), oneRedstone); - List entityList = redStack.getNearbyEntities(5, 10, 5); - for (int i = 0; i < entityList.size(); i++){ - if (entityList.get(i) instanceof Item){ - Item droppedItem = (Item) entityList.get(i); - calculateEXP(Material.AIR, Material.AIR); - int[] valueArray = new int[2266]; - getValueArray(valueArray); - player.setLevel((valueArray[droppedItem.getItemStack().getTypeId()] * droppedItem.getItemStack().getAmount()) + player.getLevel()); - droppedItem.remove(); - } - } - redStack.remove(); - } else - return; + } else { + player.sendMessage("You feel so hungry..."); + return; } - else if (arrayString.equals("[1, 2, 3, 3]") && player.hasPermission("circle.set.1233")){ + } else if (arrayString.equals("[0, 1, 1, 1]") && player.hasPermission("geometricmagic.set.0111")) { + + // using x111 because yml doesn't like 0 as first character + cost = plugin.getConfig().getInt("setcircles.x111.cost"); + if (cost > 20) cost = 20; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } else if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); } - ItemStack onePortal = new ItemStack(90, 1); - int fires = 0; - List entityList = player.getNearbyEntities(10, 10, 10); - for (int i = 0; i < entityList.size(); i++){ - if (entityList.get(i) instanceof Item){ - Item sacrifice = (Item) entityList.get(i); - if (sacrifice.getItemStack().getType() == Material.FIRE){ - fires += sacrifice.getItemStack().getAmount(); - sacrifice.remove(); + Location playerSpawn = player.getBedSpawnLocation(); + if (playerSpawn != null) { + if (playerSpawn.getBlock().getType() == Material.AIR) { + player.teleport(playerSpawn); + } else { + if (new Location(player.getWorld(), playerSpawn.getX() + 1, playerSpawn.getY(), playerSpawn.getZ()).getBlock().getType() == Material.AIR) { + player.teleport(new Location(player.getWorld(), playerSpawn.getX() + 1, playerSpawn.getY(), playerSpawn.getZ())); + } else if (new Location(player.getWorld(), playerSpawn.getX() - 1, playerSpawn.getY(), playerSpawn.getZ()).getBlock().getType() == Material.AIR) { + player.teleport(new Location(player.getWorld(), playerSpawn.getX() - 1, playerSpawn.getY(), playerSpawn.getZ())); + } else if (new Location(player.getWorld(), playerSpawn.getX(), playerSpawn.getY(), playerSpawn.getZ() + 1).getBlock().getType() == Material.AIR) { + player.teleport(new Location(player.getWorld(), playerSpawn.getX(), playerSpawn.getY(), playerSpawn.getZ() + 1)); + } else if (new Location(player.getWorld(), playerSpawn.getX(), playerSpawn.getY(), playerSpawn.getZ() - 1).getBlock().getType() == Material.AIR) { + player.teleport(new Location(player.getWorld(), playerSpawn.getX(), playerSpawn.getY(), playerSpawn.getZ() - 1)); + } else { + player.sendMessage("Your bed is not safe to teleport to!"); + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() + (cost * philosopherStoneModifier(player)))); } } } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - if (fires >= 64){ - fires -= 64; - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - effectBlock.getWorld().dropItem(effectBlock.getLocation(), onePortal); - } + } else { + player.sendMessage("You do not have a spawn set!"); + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() + (cost * philosopherStoneModifier(player)))); } - ItemStack diamondStack = new ItemStack(264 , fires); - effectBlock.getWorld().dropItem(effectBlock.getLocation(), diamondStack); - } - else if (arrayString.equals("[1, 2, 3, 4]") && player.hasPermission("circle.set.1234")){ - cost = 1; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - player.sendMessage(ChatColor.GREEN + "The four elements, like man alone, are weak. But together they form the strong fifth element: boron -Brother Silence"); - ItemStack oneRedstone = new ItemStack(331, 10); - effectBlock.getWorld().dropItem(effectBlock.getLocation(), oneRedstone); - } else - return; + } else { + player.sendMessage("You feel so hungry..."); + return; } - else if (arrayString.equals("[2, 2, 2, 3]") && player.hasPermission("circle.set.2223")){ - cost = 10; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); + } else if (arrayString.equals("[0, 0, 4, 4]") && player.hasPermission("geometricmagic.set.0044")) { + + // using x044 because yml doesn't like 0 as first character + cost = plugin.getConfig().getInt("setcircles.x044.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } else if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); + } + Location spawnLoc = effectBlockLocation; + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(spawnLoc, player)) { + // player.sendMessage("You don't have permission to do that there."); return; } - ItemStack oneRedstone = new ItemStack(331, 1); - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - Item redStack = effectBlock.getWorld().dropItem(effectBlock.getLocation(), oneRedstone); - int size = setCircleSize(actBlock); - List entityList = redStack.getNearbyEntities(size + 5, 128, size + 5); - for (int i = 0; i < entityList.size(); i++){ - if (entityList.get(i) instanceof Player){ - HumanEntity victim = (HumanEntity) entityList.get(i); - if (!victim.equals(player)){ - victim.getWorld().strikeLightningEffect(victim.getLocation()); - if (victim.getInventory().contains(Material.FIRE)){ - for (int k = 0; k < player.getInventory().getSize(); k++ ){ - if (player.getInventory().getItem(i).getType() == Material.FIRE){ - //System.out.println("removed a fire"); - int amount = player.getInventory().getItem(k).getAmount(); - player.getInventory().getItem(k).setAmount(amount - 1); - if (amount-1 <= 0){ - player.getInventory().clear(k); - } - } - } - } - else - victim.damage(20); - if (victim.isDead()){ - ItemStack oneFire = new ItemStack(51, 1); - victim.getWorld().dropItem(actBlock.getLocation(), oneFire); - } - } - } - if (entityList.get(i) instanceof Villager){ - Villager victim = (Villager) entityList.get(i); - victim.getWorld().strikeLightningEffect(victim.getLocation()); - victim.damage(20); - if (victim.isDead()){ - ItemStack oneFire = new ItemStack(51, 1); - victim.getWorld().dropItem(actBlock.getLocation(), oneFire); - } - } - } - redStack.remove(); - } else - return; + + spawnLoc.add(0.5, 1, 0.5); + effectBlock.getWorld().spawn(spawnLoc, Pig.class); + } else { + player.sendMessage("You feel so hungry..."); + return; } - else if (arrayString.equals("[2, 2, 2, 4]") && player.hasPermission("circle.set.2224")){ - cost = 10; - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + } else if (arrayString.equals("[0, 1, 4, 4]") && player.hasPermission("geometricmagic.set.0144")) { + + // using x144 because yml doesn't like 0 as first character + cost = plugin.getConfig().getInt("setcircles.x144.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } else if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - Location spawnLoc = effectBlock.getLocation(); - spawnLoc.add(0.5, 0, 0.5); - effectBlock.getWorld().spawnCreature(spawnLoc, CreatureType.ENDERMAN); - } else - return; - } - else if (arrayString.equals("[2, 2, 4, 4]") && player.hasPermission("circle.set.2244")){ - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); + } + Location spawnLoc = effectBlockLocation; + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(spawnLoc, player)) { + // player.sendMessage("You don't have permission to do that there."); return; } - Location actPoint = effectBlock.getLocation(); - int na = 0, nb = 0, ea = 0, eb = 0, sa = 0, sb = 0, wa = 0, wb = 0; - Block curBlock = effectBlock.getRelative(0, 0, -1); - while (curBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { - na++; - curBlock = curBlock.getRelative(0, 0, -1); - } - Block fineBlock = curBlock; - while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { - nb++; - fineBlock = fineBlock.getRelative(-1, 0, 0); - } - curBlock = effectBlock.getRelative(1, 0, 0); - while (curBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { - ea++; - curBlock = curBlock.getRelative(1, 0, 0); - } - fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { - eb++; - fineBlock = fineBlock.getRelative(0, 0, -1); - } - curBlock = effectBlock.getRelative(0, 0, 1); - while (curBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { - sa++; - curBlock = curBlock.getRelative(0, 0, 1); - } - fineBlock = curBlock; - while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { - sb++; - fineBlock = fineBlock.getRelative(1, 0, 0); - } - curBlock = effectBlock.getRelative(-1, 0, 0); - while (curBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { - wa++; - curBlock = curBlock.getRelative(-1, 0, 0); - } - fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { - wb++; - fineBlock = fineBlock.getRelative(0, 0, 1); - } - // north negative z, south positive z, east positive x, west - // negative x - int z = ((sa * 100 + sb) - (na * 100 + nb)); - int x = ((ea * 100 + eb) - (wa * 100 + wb)); - double actPointX = actPoint.getX(); - double actPointZ = actPoint.getZ(); - Location teleLoc = actPoint.add(x, 0, z); - double distance = Math.sqrt(Math.pow(teleLoc.getX() - actPointX, 2) + Math.pow(teleLoc.getZ() - actPointZ, 2)); - double mathRandX = philosopherStoneModifier(player) * distance/10 * Math.random(); - double mathRandZ = philosopherStoneModifier(player) * distance/10 * Math.random(); - double randX = (teleLoc.getX() - (0.5 * mathRandX)) - + (mathRandX); - double randZ = (teleLoc.getZ() - (0.5 * mathRandZ)) - + (mathRandZ); - teleLoc.setX(randX); - teleLoc.setZ(randZ); - while (teleLoc.getWorld().getChunkAt(teleLoc).isLoaded() == false){ - teleLoc.getWorld().getChunkAt(teleLoc).load(true); - } - int highestBlock = teleLoc.getWorld().getHighestBlockYAt(teleLoc) + 1; - //System.out.println( mathRandX + " " + mathRandZ ); - player.sendMessage("Safe teleportation altitude is at " + highestBlock); + + spawnLoc.add(0.5, 1, 0.5); + effectBlock.getWorld().spawn(spawnLoc, Sheep.class); + } else { + player.sendMessage("You feel so hungry..."); return; } - else if (arrayString.equals("[2, 3, 3, 3]") && player.hasPermission("circle.set.2333")){ - cost = 2; - int size = setCircleSize(actBlock); - cost = 2 + size/2; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; - } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + } else if (arrayString.equals("[0, 2, 4, 4]") && player.hasPermission("geometricmagic.set.0244")) { + + // using x244 because yml doesn't like 0 as first character + cost = plugin.getConfig().getInt("setcircles.x244.cost"); + if (cost > 20) + cost = 20; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } else if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - effectBlock.getWorld().createExplosion(effectBlock.getLocation(), (4 + size)); - } else - return; - } - else if (arrayString.equals("[3, 3, 3, 4]") && player.hasPermission("circle.set.3334")){ - cost = 2; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - alchemyFiller(Material.AIR, Material.FIRE, effectBlock.getRelative(-10, 0, -10).getLocation(), effectBlock.getRelative(10, 20, 10).getLocation(), player); - } else - return; - } - else if (arrayString.equals("[3, 3, 4, 4]") && player.hasPermission("circle.set.3344")){ - cost = 4; - int size = setCircleSize(actBlock); - cost = 4 + size/2; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); + Location spawnLoc = effectBlockLocation; + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(spawnLoc, player)) { + // player.sendMessage("You don't have permission to do that there."); return; } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - effectBlock.getWorld().createExplosion(effectBlock.getLocation(), 8 + size, true); - } else - return; + + spawnLoc.add(0.5, 1, 0.5); + effectBlock.getWorld().spawn(spawnLoc, Cow.class); + } else { + player.sendMessage("You feel so hungry..."); + return; } - else if (arrayString.equals("[3, 4, 4, 4]") && player.hasPermission("circle.set.3444")){ + } else if (arrayString.equals("[0, 3, 4, 4]") && player.hasPermission("geometricmagic.set.0344")) { + + // using x344 because yml doesn't like 0 as first character + cost = plugin.getConfig().getInt("setcircles.x344.cost"); + if (cost > 20) cost = 20; - if (!hasLearnedCircle(player, arrayString)){ - player.sendMessage("you have not yet learned circle " + arrayString + "!"); - return; + + if (!hasLearnedCircle(player, arrayString)) { + player.sendMessage("You have not yet learned circle " + arrayString + "!"); + return; + } else if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { + if (!player.hasPermission("geometricmagic.bypass.hunger")) { + player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); } - if (player.getFoodLevel() >= (cost * philosopherStoneModifier(player))) { - try { - player.setFoodLevel((int) (player.getFoodLevel() - (cost * philosopherStoneModifier(player)))); - humanTransmutation(player); - } catch (IOException e1) { - e1.printStackTrace(); - } - } else + Location spawnLoc = effectBlockLocation; + + // check if player has permission to break blocks here first + if (!checkBlockBreakSimulation(spawnLoc, player)) { + // player.sendMessage("You don't have permission to do that there."); return; + } + + spawnLoc.add(0.5, 1, 0.5); + effectBlock.getWorld().spawn(spawnLoc, Chicken.class); + } else { + player.sendMessage("You feel so hungry..."); + return; } - else{ - player.sendMessage("You do not have permission to use " + arrayString + " or set circle does not exist"); - } - effectBlock.getWorld().strikeLightningEffect(effectBlock.getLocation()); + } else { + player.sendMessage("You do not have permission to use " + arrayString + " or set circle does not exist"); } - - public static int setCircleSize (Block actBlock){ + effectBlock.getWorld().strikeLightningEffect(effectBlockLocation); + } + + public static int setCircleSize(Block actBlock) { + // limit sizes + int limitsize = plugin.getConfig().getInt("setcircles.limitsize"); + int na = 0, nb = 0, ea = 0, eb = 0, sa = 0, sb = 0, wa = 0, wb = 0, nc = 0, ec = 0, sc = 0, wc = 0; Block curBlock = actBlock.getRelative(0, 0, -5); - while (curBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + while (curBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE || na == limitsize) { na++; curBlock = curBlock.getRelative(0, 0, -1); } Block fineBlock = curBlock; - while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE || nb == limitsize) { nb++; fineBlock = fineBlock.getRelative(-1, 0, 0); } fineBlock = curBlock; - while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE || nc == limitsize) { nc++; fineBlock = fineBlock.getRelative(1, 0, 0); } curBlock = actBlock.getRelative(5, 0, 0); - while (curBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (curBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE || ea == limitsize) { ea++; curBlock = curBlock.getRelative(1, 0, 0); } fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE || eb == limitsize) { eb++; fineBlock = fineBlock.getRelative(0, 0, -1); } fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE || ec == limitsize) { ec++; fineBlock = fineBlock.getRelative(0, 0, 1); } curBlock = actBlock.getRelative(0, 0, 5); - while (curBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + while (curBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE || sa == limitsize) { sa++; curBlock = curBlock.getRelative(0, 0, 1); } fineBlock = curBlock; - while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(1, 0, 0).getType() == Material.REDSTONE_WIRE || sb == limitsize) { sb++; fineBlock = fineBlock.getRelative(1, 0, 0); } fineBlock = curBlock; - while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE || sc == limitsize) { sc++; fineBlock = fineBlock.getRelative(-1, 0, 0); } curBlock = actBlock.getRelative(-5, 0, 0); - while (curBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE) { + while (curBlock.getRelative(-1, 0, 0).getType() == Material.REDSTONE_WIRE || wa == limitsize) { wa++; curBlock = curBlock.getRelative(-1, 0, 0); } fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(0, 0, 1).getType() == Material.REDSTONE_WIRE || wb == limitsize) { wb++; fineBlock = fineBlock.getRelative(0, 0, 1); } fineBlock = curBlock; - while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE) { + while (fineBlock.getRelative(0, 0, -1).getType() == Material.REDSTONE_WIRE || wc == limitsize) { wc++; fineBlock = fineBlock.getRelative(0, 0, -1); } int size = 0; - if (wa == ea && na == sa && wb == eb && nb == sb && wc == ec && nc == sc && wa == na){ + if (wa == ea && na == sa && wb == eb && nb == sb && wc == ec && nc == sc && wa == na) { size = wa; } return size; } - public static void alchemyCheck(Material a, Material b, Location circleStart, Location circleEnd, Location start, - Location end, Player player, int width) { + public static void alchemyCheck(Material a, byte fromData, Material b, byte toData, Location circleStart, Location circleEnd, Location start, Location end, Player player, int width) { Block startBlock = circleStart.getBlock(); int xIteration = 0; int yIteration = 0; int zIteration = 0; if (circleStart.getX() < circleEnd.getX()) { if (circleStart.getZ() < circleEnd.getZ()) { - //east - //System.out.println("alchemyCheck east"); + // east + // System.out.println("alchemyCheck east"); while (startBlock.getY() <= circleEnd.getY()) { while (startBlock.getX() <= circleEnd.getX()) { while (startBlock.getZ() <= circleEnd.getZ()) { - if (startBlock.getType() != Material.AIR){ - alchemyFiller(a, b, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), start.getBlock().getRelative(xIteration * width + width - 1, yIteration * width + width - 1, (zIteration * width + (width - 1))).getLocation(), player); + if (startBlock.getType() != Material.AIR) { + alchemyFiller(a, fromData, b, toData, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), + start.getBlock().getRelative(xIteration * width + width - 1, yIteration * width + width - 1, (zIteration * width + (width - 1))).getLocation(), player, true); } zIteration++; startBlock = startBlock.getRelative(0, 0, 1); } xIteration++; - startBlock = circleStart.getBlock().getRelative(xIteration, - yIteration, 0); + startBlock = circleStart.getBlock().getRelative(xIteration, yIteration, 0); zIteration = 0; } yIteration++; @@ -901,46 +1664,46 @@ public static void alchemyCheck(Material a, Material b, Location circleStart, Lo startBlock = circleStart.getBlock().getRelative(0, yIteration, 0); } } else { - //north - //System.out.println("alchemyCheck north"); + // north + // System.out.println("alchemyCheck north"); while (startBlock.getY() <= circleEnd.getY()) { while (startBlock.getZ() >= circleEnd.getZ()) { while (startBlock.getX() <= circleEnd.getX()) { - if (startBlock.getType() != Material.AIR){ - alchemyFiller(a, b, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), start.getBlock().getRelative(xIteration * width + width - 1, yIteration * width + width - 1, (zIteration * width - (width - 1))).getLocation(), player); + if (startBlock.getType() != Material.AIR) { + alchemyFiller(a, fromData, b, toData, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), + start.getBlock().getRelative(xIteration * width + width - 1, yIteration * width + width - 1, (zIteration * width - (width - 1))).getLocation(), player, true); } xIteration++; - //System.out.println("xloop " + xIteration); + // System.out.println("xloop " + xIteration); startBlock = startBlock.getRelative(1, 0, 0); } zIteration--; - //System.out.println("zloop " + zIteration); - startBlock = circleStart.getBlock().getRelative(0, - yIteration, zIteration); + // System.out.println("zloop " + zIteration); + startBlock = circleStart.getBlock().getRelative(0, yIteration, zIteration); xIteration = 0; } yIteration++; - //System.out.println("yloop " + yIteration); + // System.out.println("yloop " + yIteration); zIteration = 0; startBlock = circleStart.getBlock().getRelative(0, yIteration, 0); } } } else { if (circleStart.getZ() > circleEnd.getZ()) { - //west - //System.out.println("alchemyCheck west"); + // west + // System.out.println("alchemyCheck west"); while (startBlock.getY() <= circleEnd.getY()) { while (startBlock.getX() >= circleEnd.getX()) { while (startBlock.getZ() >= circleEnd.getZ()) { - if (startBlock.getType() != Material.AIR){ - alchemyFiller(a, b, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), start.getBlock().getRelative(xIteration * width - (width - 1), yIteration * width + width - 1, (zIteration * width - (width - 1))).getLocation(), player); + if (startBlock.getType() != Material.AIR) { + alchemyFiller(a, fromData, b, toData, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), + start.getBlock().getRelative(xIteration * width - (width - 1), yIteration * width + width - 1, (zIteration * width - (width - 1))).getLocation(), player, true); } zIteration--; startBlock = startBlock.getRelative(0, 0, -1); } xIteration--; - startBlock = circleStart.getBlock().getRelative(xIteration, - yIteration, 0); + startBlock = circleStart.getBlock().getRelative(xIteration, yIteration, 0); zIteration = 0; } yIteration++; @@ -948,26 +1711,26 @@ public static void alchemyCheck(Material a, Material b, Location circleStart, Lo startBlock = circleStart.getBlock().getRelative(0, yIteration, 0); } } else { - //south - //System.out.println("alchemyCheck south"); + // south + // System.out.println("alchemyCheck south"); while (startBlock.getY() <= circleEnd.getY()) { while (startBlock.getZ() <= circleEnd.getZ()) { while (startBlock.getX() >= circleEnd.getX()) { - if (startBlock.getType() != Material.AIR){ - alchemyFiller(a, b, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), start.getBlock().getRelative(xIteration * width - (width - 1), yIteration * width + width - 1, (zIteration * width + (width - 1))).getLocation(), player); + if (startBlock.getType() != Material.AIR) { + alchemyFiller(a, fromData, b, toData, start.getBlock().getRelative(xIteration * width, yIteration * width, zIteration * width).getLocation(), + start.getBlock().getRelative(xIteration * width - (width - 1), yIteration * width + width - 1, (zIteration * width + (width - 1))).getLocation(), player, true); } xIteration--; - //System.out.println("xloop"); + // System.out.println("xloop"); startBlock = startBlock.getRelative(-1, 0, 0); } zIteration++; - //System.out.println("zloop"); - startBlock = circleStart.getBlock().getRelative(0, - yIteration, zIteration); + // System.out.println("zloop"); + startBlock = circleStart.getBlock().getRelative(0, yIteration, zIteration); xIteration = 0; } yIteration++; - //System.out.println("yloop"); + // System.out.println("yloop"); zIteration = 0; startBlock = circleStart.getBlock().getRelative(0, yIteration, 0); } @@ -975,411 +1738,66 @@ public static void alchemyCheck(Material a, Material b, Location circleStart, Lo } return; } - - public static void alchemyFiller(Material a, Material b, Location start, - Location end, Player player) { - //System.out.println("alchemyFiller"); - Block startBlock = start.getBlock(); - int xIteration = 0; - int yIteration = 0; - int zIteration = 0; - if (start.getX() < end.getX()) { - if (start.getZ() < end.getZ()) { - //east - //System.out.println("alchemyFiller east"); - while (startBlock.getY() <= end.getY()) { - while (startBlock.getX() <= end.getX()) { - while (startBlock.getZ() <= end.getZ()) { - transmuteBlock(a, b, startBlock, player); - startBlock = startBlock.getRelative(0, 0, 1); - } - xIteration++; - startBlock = start.getBlock().getRelative(xIteration, - yIteration, 0); - } - yIteration++; - xIteration = 0; - startBlock = start.getBlock().getRelative(0, yIteration, 0); - } - } else { - //north - //System.out.println("alchemyFiller north"); - while (startBlock.getY() <= end.getY()) { - while (startBlock.getZ() >= end.getZ()) { - while (startBlock.getX() <= end.getX()) { - transmuteBlock(a, b, startBlock, player); - startBlock = startBlock.getRelative(1, 0, 0); - } - zIteration--; - startBlock = start.getBlock().getRelative(0, - yIteration, zIteration); - } - yIteration++; - zIteration = 0; - startBlock = start.getBlock().getRelative(0, yIteration, 0); - } - } - } else { - if (start.getZ() > end.getZ()) { - //west - //System.out.println("alchemyFiller west"); - while (startBlock.getY() <= end.getY()) { - while (startBlock.getX() >= end.getX()) { - while (startBlock.getZ() >= end.getZ()) { - transmuteBlock(a, b, startBlock, player); - startBlock = startBlock.getRelative(0, 0, -1); - } - xIteration--; - startBlock = start.getBlock().getRelative(xIteration, - yIteration, 0); - } - yIteration++; - xIteration = 0; - startBlock = start.getBlock().getRelative(0, yIteration, 0); - } - } else { - //south - //System.out.println("alchemyFiller south"); - while (startBlock.getY() <= end.getY()) { - while (startBlock.getZ() <= end.getZ()) { - while (startBlock.getX() >= end.getX()) { - transmuteBlock(a, b, startBlock, player); - startBlock = startBlock.getRelative(-1, 0, 0); - //System.out.println("xloopfiller"); - } - zIteration++; - //System.out.println("zloopfiller"); - startBlock = start.getBlock().getRelative(0, - yIteration, zIteration); - } - yIteration++; - //System.out.println("yloopfiller"); - zIteration = 0; - startBlock = start.getBlock().getRelative(0, yIteration, 0); - } - } - } - return; - } - public static void transmuteBlock(Material a, Material b, Block startBlock, - Player player) { - if (startBlock.getType() == a) { - int exp = calculateEXP(a, b); - if (-1 * player.getLevel() < (exp * philosopherStoneModifier(player))) { - player.setLevel((int) (player.getLevel() + (exp * philosopherStoneModifier(player)))); - startBlock.setType(b); - //System.out.println("transmuted block"); - //System.out.println(startBlock.getX() + " " + startBlock.getY() + " " + startBlock.getZ()); - return; - } else - return; - } else - return; + public static void alchemyFiller(Material a, byte fromData, Material b, byte toData, Location start, Location end, Player player, boolean charge) { + // System.out.println("alchemyFiller"); + String playerName = player.getName(); + long rate = plugin.getConfig().getLong("transmutation.rate"); + + new Thread(new GeometricMagicTransmutationThread(plugin, rate, a, fromData, b, toData, start, end, playerName, charge)).start(); } - public static int calculateEXP(Material a, Material b) { - int[] valueArray = new int[2266]; - // array index is block id, value in array is xp - Arrays.fill(valueArray, 0); - valueArray[0] = 0; - valueArray[1] = 6; - valueArray[2] = 1; - valueArray[3] = 1; - valueArray[4] = 4; - valueArray[5] = 4; - valueArray[6] = 8; - valueArray[7] = 0; - valueArray[8] = 0; - valueArray[9] = 1; - valueArray[10] = 0; - valueArray[11] = 200; - valueArray[12] = 1; - valueArray[13] = 2; - valueArray[14] = 384; - valueArray[15] = 96; - valueArray[16] = 16; - valueArray[17] = 16; - valueArray[18] = 1; - valueArray[19] = 0; - valueArray[20] = 3; - valueArray[21] = 144; - valueArray[22] = 216; - valueArray[23] = 51; - valueArray[24] = 4; - valueArray[25] = 40; - valueArray[26] = 48; - valueArray[27] = 384; - valueArray[28] = 96; - valueArray[29] = 153; - valueArray[30] = 24; - valueArray[31] = 1; - valueArray[32] = 1; - valueArray[33] = 132; - valueArray[34] = 0; - valueArray[35] = 12; - valueArray[36] = 0; - valueArray[37] = 48; - valueArray[38] = 48; - valueArray[39] = 32; - valueArray[40] = 32; - valueArray[41] = 3456; - valueArray[42] = 864; - valueArray[43] = 8; - valueArray[44] = 4; - valueArray[45] = 24; - valueArray[46] = 484; - valueArray[47] = 96; - valueArray[48] = 4; - valueArray[49] = 192; - valueArray[50] = 4; - valueArray[51] = 1; - valueArray[52] = 0; - valueArray[53] = 6; - valueArray[54] = 32; - valueArray[55] = 8; - valueArray[56] = 1536; - valueArray[57] = 13824; - valueArray[58] = 16; - valueArray[59] = 4; - valueArray[60] = 1; - valueArray[61] = 32; - valueArray[62] = 32; - valueArray[63] = 0; - valueArray[64] = 24; - valueArray[65] = 7; - valueArray[66] = 36; - valueArray[67] = 6; - valueArray[68] = 0; - valueArray[69] = 6; - valueArray[70] = 12; - valueArray[71] = 576; - valueArray[72] = 8; - valueArray[73] = 32; - valueArray[74] = 32; - valueArray[75] = 10; - valueArray[76] = 10; - valueArray[77] = 12; - valueArray[78] = 1; - valueArray[79] = 4; - valueArray[80] = 4; - valueArray[81] = 8; - valueArray[82] = 16; - valueArray[83] = 8; - valueArray[84] = 1568; - valueArray[85] = 6; - valueArray[86] = 64; - valueArray[87] = 1; - valueArray[88] = 2; - valueArray[89] = 128; - valueArray[90] = 0; - valueArray[91] = 68; - valueArray[92] = 163; - valueArray[93] = 46; - valueArray[94] = 46; - valueArray[95] = 0; - valueArray[96] = 12; - valueArray[97] = 0; - valueArray[98] = 6; - valueArray[99] = 32; - valueArray[100] = 32; - valueArray[101] = 36; - valueArray[102] = 1; - valueArray[103] = 64; - valueArray[104] = 16; - valueArray[105] = 7; - valueArray[106] = 1; - valueArray[107] = 16; - valueArray[108] = 36; - valueArray[109] = 9; - valueArray[110] = 1; - valueArray[111] = 0; - valueArray[112] = 0; - valueArray[113] = 0; - valueArray[114] = 0; - valueArray[115] = 8; - valueArray[116] = 0; - valueArray[117] = 0; - valueArray[118] = 0; - valueArray[119] = 0; - valueArray[120] = 0; - valueArray[121] = 1; - valueArray[122] = 0; - int valueDifference = valueArray[a.getId()] - valueArray[b.getId()]; - return valueDifference; + public static double getBalance(Player player) { + + if (getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + Economy econ = GeometricMagic.getEconomy(); + + double balance = econ.getBalance(player.getName()); + + return balance; + } else if (getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + double balance = player.getLevel(); + + return balance; + } + return 0; } - - public static int[] getValueArray (int[] valueArray){ - //int[] valueArray = new int[2266]; - // array index is block id, value in array is xp - Arrays.fill(valueArray, 0); - valueArray[0] = 0; - valueArray[1] = 6; - valueArray[2] = 1; - valueArray[3] = 1; - valueArray[4] = 4; - valueArray[5] = 4; - valueArray[6] = 8; - valueArray[7] = 0; - valueArray[8] = 0; - valueArray[9] = 1; - valueArray[10] = 0; - valueArray[11] = 200; - valueArray[12] = 1; - valueArray[13] = 2; - valueArray[14] = 384; - valueArray[15] = 96; - valueArray[16] = 16; - valueArray[17] = 16; - valueArray[18] = 1; - valueArray[19] = 0; - valueArray[20] = 3; - valueArray[21] = 144; - valueArray[22] = 216; - valueArray[23] = 51; - valueArray[24] = 4; - valueArray[25] = 40; - valueArray[26] = 48; - valueArray[27] = 384; - valueArray[28] = 96; - valueArray[29] = 153; - valueArray[30] = 24; - valueArray[31] = 1; - valueArray[32] = 1; - valueArray[33] = 132; - valueArray[34] = 0; - valueArray[35] = 12; - valueArray[36] = 0; - valueArray[37] = 48; - valueArray[38] = 48; - valueArray[39] = 32; - valueArray[40] = 32; - valueArray[41] = 3456; - valueArray[42] = 864; - valueArray[43] = 8; - valueArray[44] = 4; - valueArray[45] = 24; - valueArray[46] = 484; - valueArray[47] = 96; - valueArray[48] = 4; - valueArray[49] = 192; - valueArray[50] = 4; - valueArray[51] = 1; - valueArray[52] = 0; - valueArray[53] = 6; - valueArray[54] = 32; - valueArray[55] = 8; - valueArray[56] = 1536; - valueArray[57] = 13824; - valueArray[58] = 16; - valueArray[59] = 4; - valueArray[60] = 1; - valueArray[61] = 32; - valueArray[62] = 32; - valueArray[63] = 0; - valueArray[64] = 24; - valueArray[65] = 7; - valueArray[66] = 36; - valueArray[67] = 6; - valueArray[68] = 0; - valueArray[69] = 6; - valueArray[70] = 12; - valueArray[71] = 576; - valueArray[72] = 8; - valueArray[73] = 32; - valueArray[74] = 32; - valueArray[75] = 10; - valueArray[76] = 10; - valueArray[77] = 12; - valueArray[78] = 1; - valueArray[79] = 4; - valueArray[80] = 4; - valueArray[81] = 8; - valueArray[82] = 16; - valueArray[83] = 8; - valueArray[84] = 1568; - valueArray[85] = 6; - valueArray[86] = 64; - valueArray[87] = 1; - valueArray[88] = 2; - valueArray[89] = 128; - valueArray[90] = 0; - valueArray[91] = 68; - valueArray[92] = 163; - valueArray[93] = 46; - valueArray[94] = 46; - valueArray[95] = 0; - valueArray[96] = 12; - valueArray[97] = 0; - valueArray[98] = 6; - valueArray[99] = 32; - valueArray[100] = 32; - valueArray[101] = 36; - valueArray[102] = 1; - valueArray[103] = 64; - valueArray[104] = 16; - valueArray[105] = 7; - valueArray[106] = 1; - valueArray[107] = 16; - valueArray[108] = 36; - valueArray[109] = 9; - valueArray[110] = 1; - valueArray[111] = 0; - valueArray[112] = 0; - valueArray[113] = 0; - valueArray[114] = 0; - valueArray[115] = 8; - valueArray[116] = 0; - valueArray[117] = 0; - valueArray[118] = 0; - valueArray[119] = 0; - valueArray[120] = 0; - valueArray[121] = 1; - valueArray[122] = 0; - return valueArray; + + public static double calculatePay(Material a, byte fromData , Material b, byte toData , Player player) { + double pay = (getBlockValue(plugin, a.getId(), (int) fromData) - getBlockValue(plugin, b.getId(), (int) toData)); + + // Apply Philosopher's Stone to transmutes config variable + String stoneConfig = plugin.getConfig().getString("transmutation.stone"); + if (stoneConfig == "true") { + return (double) (pay * philosopherStoneModifier(player)); + } else { + return pay; + } } - - public static double philosopherStoneModifier (Player player){ + + public static double philosopherStoneModifier(Player player) { double modifier = 1; int stackCount = 0; PlayerInventory inventory = player.getInventory(); - for (int i = 0; i < inventory.getSize(); i++ ){ - if (inventory.getItem(i).getType() == Material.PORTAL) + for (int i = 0; i < inventory.getSize(); i++) { + if (inventory.getItem(i) != null && inventory.getItem(i).getType() == Material.PORTAL) stackCount += inventory.getItem(i).getAmount(); } - modifier = 1/(Math.pow(2, stackCount)); + float multiplierModifier = (float) plugin.getConfig().getDouble("philosopherstone.modifier"); + + modifier = 1 / (Math.pow(2, stackCount) * multiplierModifier); return modifier; } - - public static boolean checkSacrifices (Player player) throws IOException{ - File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); - if (!myFile.exists()) - { - return false; - } - Scanner inputFile = new Scanner(myFile); - while (inputFile.hasNextLine()){ - String name = inputFile.nextLine(); - if (name.equals(player.getName())) - return true; - inputFile.nextLine(); - } - inputFile.close(); - return false; - //playername - //[1, 1, 1, 2] - } - - public static void humanTransmutation (Player player) throws IOException{ + + public static void humanTransmutation(Player player) throws IOException { if (new File("plugins/GeometricMagic/").mkdirs()) - System.out.println("sacrifices file created"); + System.out.println("[GeometricMagic] Sacrifices file created."); File myFile = new File("plugins/GeometricMagic/sacrifices.txt"); - if (myFile.exists()) - { + if (myFile.exists()) { Scanner inputFile = new Scanner(myFile); - while (inputFile.hasNextLine()){ + while (inputFile.hasNextLine()) { String name = inputFile.nextLine(); - if (name.equals(player.getDisplayName())){ + if (name.equals(player.getDisplayName())) { FileWriter dWriter = new FileWriter("plugins/GeometricMagic/sacrificed.txt", true); PrintWriter dFile = new PrintWriter(dWriter); dFile.println(player.getDisplayName()); @@ -1388,10 +1806,9 @@ public static void humanTransmutation (Player player) throws IOException{ } } inputFile.close(); - } - else{ + } else { PrintWriter outputFile = new PrintWriter("plugins/GeometricMagic/sacrifices.txt"); - System.out.println("sacrifices file created"); + System.out.println("[GeometricMagic] Sacrifices file created."); outputFile.close(); } FileWriter fWriter = new FileWriter("plugins/GeometricMagic/sacrifices.txt", true); @@ -1401,67 +1818,524 @@ public static void humanTransmutation (Player player) throws IOException{ player.sendMessage("You have committed the taboo! Crafting is your sacrifice, knowledge your reward."); outputFile.close(); } - - public static boolean checkSacrificed (Player player) throws IOException{ - File myFile = new File("plugins/GeometricMagic/sacrificed.txt"); - if (!myFile.exists()) - { - return false; - } - Scanner inputFile = new Scanner(myFile); - while (inputFile.hasNextLine()){ - String name = inputFile.nextLine(); - if (name.equals(player.getName())) - return true; - } - inputFile.close(); - return false; - //playername - } - - public static boolean hasLearnedCircle (Player player, String circle) throws IOException{ + + public static boolean hasLearnedCircle(Player player, String circle) throws IOException { File myFile = new File("plugins/GeometricMagic/" + player.getName() + ".txt"); - if (!myFile.exists()) - { - return false; + if (!myFile.exists()) { + return false; } Scanner inputFile = new Scanner(myFile); - while (inputFile.hasNextLine()){ + while (inputFile.hasNextLine()) { String name = inputFile.nextLine(); - if (name.equals(circle)) + if (name.equals(circle)) { + inputFile.close(); return true; + } } inputFile.close(); return false; } - - public static boolean learnCircle (Player player, String circle, Block actBlock) throws IOException{ + + public static boolean learnCircle(Player player, String circle, Block actBlock) throws IOException { boolean status = false; - //System.out.println("learnCircle"); + // System.out.println("learnCircle"); ItemStack oneRedstone = new ItemStack(331, 1); Item redStack = actBlock.getWorld().dropItem(actBlock.getLocation(), oneRedstone); List entityList = redStack.getNearbyEntities(2, 10, 2); - for (int i = 0; i < entityList.size(); i++){ - if (entityList.get(i) instanceof Enderman){ - if (new File("plugins/GeometricMagic/").mkdirs()) - System.out.println("file created for " + player.getName()); - File myFile = new File("plugins/GeometricMagic/" + player.getName() + ".txt"); - if (myFile.exists()) - { - FileWriter fWriter = new FileWriter("plugins/GeometricMagic/" + player.getName() + ".txt", true); - PrintWriter outputFile = new PrintWriter(fWriter); - outputFile.println(circle); - outputFile.close(); - } - else{ - PrintWriter outputFile = new PrintWriter("plugins/GeometricMagic/" + player.getName() + ".txt"); - outputFile.println(circle); - outputFile.close(); - } - status = true; + for (int i = 0; i < entityList.size(); i++) { + if (entityList.get(i) instanceof Enderman) { + if (new File("plugins/GeometricMagic/").mkdirs()) + System.out.println("[GeometricMagic] File created for " + player.getName()); + File myFile = new File("plugins/GeometricMagic/" + player.getName() + ".txt"); + if (myFile.exists()) { + FileWriter fWriter = new FileWriter("plugins/GeometricMagic/" + player.getName() + ".txt", true); + PrintWriter outputFile = new PrintWriter(fWriter); + outputFile.println(circle); + outputFile.close(); + } else { + PrintWriter outputFile = new PrintWriter("plugins/GeometricMagic/" + player.getName() + ".txt"); + outputFile.println(circle); + outputFile.close(); } + status = true; } + } redStack.remove(); return status; } + + public static void storageCircle(Location startLoc, Location endLoc, Player player, int size) { + File folder = new File("plugins/GeometricMagic/storage/"); + File file = new File("plugins/GeometricMagic/storage/" + player.getName() + "." + String.valueOf(size)); + if (folder.exists()) { + // Load blocks + if (file.exists()) { + try { + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + storageCircleLoad(startLoc, endLoc, player, size, file); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + // Store blocks + else { + try { + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + storageCircleStore(startLoc, endLoc, player, size, file); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + } + else { + // Store blocks + if(folder.mkdirs()) { + try { + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + storageCircleStore(startLoc, endLoc, player, size, file); + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + else + System.out.println("[GeometricMagic] Error creating necessary folder(s)!" + + " Check your read/write permissions"); + } + } + + public static void storageCircleLoad(Location startLoc, Location endLoc, Player player, int size, File file) throws FileNotFoundException { + World world = player.getWorld(); + Scanner in = new Scanner(file); + + if (startLoc.getBlockX() > endLoc.getBlockX()) { + if (startLoc.getBlockZ() > endLoc.getBlockZ()) { + for (int x = startLoc.getBlockX(); x >= endLoc.getBlockX(); x--) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z >= endLoc.getBlockZ(); z--) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + String newBlockString = in.next(); + String[] newBlockStringArray = newBlockString.split(","); + int newBlockID = Integer.parseInt(newBlockStringArray[0]); + byte newBlockData = Byte.parseByte(newBlockStringArray[1]); + + // Block break + if (block.getTypeId() != 0 && newBlockID == 0) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block place + else if (block.getTypeId() == 0 && newBlockID != 0) { + if (!checkPlaceBlacklist(newBlockID)) { + if (checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block break and place + else if (block.getTypeId() != 0 && newBlockID != 0) { + if (!checkBreakBlacklist(block.getTypeId()) && !checkPlaceBlacklist(newBlockID)) { + if (checkBlockBreakSimulation(loc, player) && checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + } + } + } + } + else { + for (int x = startLoc.getBlockX(); x >= endLoc.getBlockX(); x--) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z <= endLoc.getBlockZ(); z++) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + String newBlockString = in.next(); + String[] newBlockStringArray = newBlockString.split(","); + int newBlockID = Integer.parseInt(newBlockStringArray[0]); + byte newBlockData = Byte.parseByte(newBlockStringArray[1]); + + // Block break + if (block.getTypeId() != 0 && newBlockID == 0) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block place + else if (block.getTypeId() == 0 && newBlockID != 0) { + if (!checkPlaceBlacklist(newBlockID)) { + if (checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block break and place + else if (block.getTypeId() != 0 && newBlockID != 0) { + if (!checkBreakBlacklist(block.getTypeId()) && !checkPlaceBlacklist(newBlockID)) { + if (checkBlockBreakSimulation(loc, player) && checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + } + } + } + } + } + else { + if (startLoc.getBlockZ() > endLoc.getBlockZ()) { + for (int x = startLoc.getBlockX(); x <= endLoc.getBlockX(); x++) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z >= endLoc.getBlockZ(); z--) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + String newBlockString = in.next(); + String[] newBlockStringArray = newBlockString.split(","); + int newBlockID = Integer.parseInt(newBlockStringArray[0]); + byte newBlockData = Byte.parseByte(newBlockStringArray[1]); + + // Block break + if (block.getTypeId() != 0 && newBlockID == 0) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block place + else if (block.getTypeId() == 0 && newBlockID != 0) { + if (!checkPlaceBlacklist(newBlockID)) { + if (checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block break and place + else if (block.getTypeId() != 0 && newBlockID != 0) { + if (!checkBreakBlacklist(block.getTypeId()) && !checkPlaceBlacklist(newBlockID)) { + if (checkBlockBreakSimulation(loc, player) && checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + } + } + } + } + else { + for (int x = startLoc.getBlockX(); x <= endLoc.getBlockX(); x++) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z <= endLoc.getBlockZ(); z++) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + String newBlockString = in.next(); + String[] newBlockStringArray = newBlockString.split(","); + int newBlockID = Integer.parseInt(newBlockStringArray[0]); + byte newBlockData = Byte.parseByte(newBlockStringArray[1]); + + // Block break + if (block.getTypeId() != 0 && newBlockID == 0) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block place + else if (block.getTypeId() == 0 && newBlockID != 0) { + if (!checkPlaceBlacklist(newBlockID)) { + if (checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + // Block break and place + else if (block.getTypeId() != 0 && newBlockID != 0) { + if (!checkBreakBlacklist(block.getTypeId()) && !checkPlaceBlacklist(newBlockID)) { + if (checkBlockBreakSimulation(loc, player) && checkBlockPlaceSimulation(loc, newBlockID, newBlockData, loc, player)) { + block.setTypeId(newBlockID); + block.setData(newBlockData); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + } + } + } + } + } + } + } + in.close(); + file.delete(); + } + + public static void storageCircleStore(Location startLoc, Location endLoc, Player player, int size, File file) throws FileNotFoundException { + World world = player.getWorld(); + PrintWriter out = new PrintWriter(file); + + if (startLoc.getBlockX() > endLoc.getBlockX()) { + if (startLoc.getBlockZ() > endLoc.getBlockZ()) { + for (int x = startLoc.getBlockX(); x >= endLoc.getBlockX(); x--) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z >= endLoc.getBlockZ(); z--) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + + if (block.getType() != Material.AIR) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + out.println(String.valueOf(block.getTypeId()) + "," + String.valueOf(block.getData())); + block.setType(Material.AIR); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + out.println("0,0"); + } + } + else { + out.println("0,0"); + } + } + } + } + } + else { + for (int x = startLoc.getBlockX(); x >= endLoc.getBlockX(); x--) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z <= endLoc.getBlockZ(); z++) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + + if (block.getType() != Material.AIR) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + out.println(String.valueOf(block.getTypeId()) + "," + String.valueOf(block.getData())); + block.setType(Material.AIR); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + out.println("0,0"); + } + } + else { + out.println("0,0"); + } + } + } + } + } + } + else { + if (startLoc.getBlockZ() > endLoc.getBlockZ()) { + for (int x = startLoc.getBlockX(); x <= endLoc.getBlockX(); x++) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z >= endLoc.getBlockZ(); z--) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + + if (block.getType() != Material.AIR) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + out.println(String.valueOf(block.getTypeId()) + "," + String.valueOf(block.getData())); + block.setType(Material.AIR); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + out.println("0,0"); + } + } + else { + out.println("0,0"); + } + } + } + } + } + else { + for (int x = startLoc.getBlockX(); x <= endLoc.getBlockX(); x++) { + for (int y = startLoc.getBlockY(); y <= endLoc.getBlockY(); y++) { + for (int z = startLoc.getBlockZ(); z <= endLoc.getBlockZ(); z++) { + Location loc = new Location(world, x, y, z); + Block block = loc.getBlock(); + + if (block.getType() != Material.AIR) { + if (!checkBreakBlacklist(block.getTypeId())) { + if (checkBlockBreakSimulation(loc, player)) { + out.println(String.valueOf(block.getTypeId()) + "," + String.valueOf(block.getData())); + block.setType(Material.AIR); + } + } + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + out.println("0,0"); + } + } + else { + out.println("0,0"); + } + } + } + } + } + } + out.close(); + } + + public static String getTransmutationCostSystem(GeometricMagic plugin) { + return plugin.getConfig().getString("transmutation.cost").toString(); + } + + public static Integer getBlockValue(GeometricMagic plugin, int ID, int Data) { + return plugin.getConfig().getInt("values." + ID + "." + Data); + } + + // Lyneira's Code Start + public static boolean checkBlockPlaceSimulation(Location target, int typeId, byte data, Location placedAgainst, Player player) { + Block placedBlock = target.getBlock(); + BlockState replacedBlockState = placedBlock.getState(); + int oldType = replacedBlockState.getTypeId(); + byte oldData = replacedBlockState.getRawData(); + + // Set the new state without physics. + placedBlock.setTypeIdAndData(typeId, data, false); + BlockPlaceEvent placeEvent = new BlockPlaceEvent(placedBlock, replacedBlockState, placedAgainst.getBlock(), null, player, true); + getPluginManager().callEvent(placeEvent); + + // Revert to the old state without physics. + placedBlock.setTypeIdAndData(oldType, oldData, false); + if (placeEvent.isCancelled()) + return false; + return true; + } + + public static boolean checkBlockBreakSimulation(Location target, Player player) { + Block block = target.getBlock(); + BlockBreakEvent breakEvent = new BlockBreakEvent(block, player); + getPluginManager().callEvent(breakEvent); + if (breakEvent.isCancelled()) + return false; + return true; + } + + // Lyneira's Code End + + public static boolean checkBreakBlacklist(int m) { + List blacklist = plugin.getConfig().getStringList("blacklist.break"); + for (String s : blacklist) { + if (s.equals(String.valueOf(m))) + return true; + } + return false; + } + + public static boolean checkPlaceBlacklist(int m) { + List blacklist = plugin.getConfig().getStringList("blacklist.place"); + for (String s : blacklist) { + if (s.equals(String.valueOf(m))) + return true; + } + return false; + } + + public static PluginManager getPluginManager() { + return plugin.getServer().getPluginManager(); + } } diff --git a/src/me/cakenggt/GeometricMagic/GeometricMagicTransmutationThread.java b/src/me/cakenggt/GeometricMagic/GeometricMagicTransmutationThread.java new file mode 100644 index 0000000..19c005f --- /dev/null +++ b/src/me/cakenggt/GeometricMagic/GeometricMagicTransmutationThread.java @@ -0,0 +1,290 @@ +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ + +package me.cakenggt.GeometricMagic; + +import net.h31ix.anticheat.api.AnticheatAPI; +import net.h31ix.anticheat.manage.CheckType; +import net.milkbowl.vault.economy.Economy; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +public class GeometricMagicTransmutationThread implements Runnable { + private GeometricMagic plugin; + private long rate; + private Material a; + private byte fromData; + private Material b; + private byte toData; + private Location start; + private Location end; + private String playerName; + private boolean charge; + + public GeometricMagicTransmutationThread(GeometricMagic instance, + long rateLong, + Material aMat, + byte fromDataByte, + Material bMat, + byte toDataByte, + Location startLoc, + Location endLoc, + String playerNameString, + boolean chargeBool) { + plugin = instance; + rate = rateLong; + a = aMat; + fromData = fromDataByte; + b = bMat; + toData = toDataByte; + start = startLoc; + end = endLoc; + playerName = playerNameString; + charge = chargeBool; + } + + public void run() { + if (start.getX() < end.getX()) { + if (start.getZ() < end.getZ()) { + for (int x = (int) start.getX(); x <= end.getX(); x++) { + for (int y = (int) start.getY(); y <= end.getY(); y++) { + for (int z = (int) start.getZ(); z <= end.getZ(); z++) { + Location loc = new Location(start.getWorld(), (double) x, (double) y, (double) z); + transmuteBlock(a, fromData, b, toData, loc, playerName, charge); + try { + Thread.sleep(rate); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + else { + for (int x = (int) start.getX(); x <= end.getX(); x++) { + for (int y = (int) start.getY(); y <= end.getY(); y++) { + for (int z = (int) start.getZ(); z >= end.getZ(); z--) { + Location loc = new Location(start.getWorld(), (double) x, (double) y, (double) z); + transmuteBlock(a, fromData, b, toData, loc, playerName, charge); + try { + Thread.sleep(rate); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + } + else { + if (start.getZ() < end.getZ()) { + for (int x = (int) start.getX(); x >= end.getX(); x--) { + for (int y = (int) start.getY(); y <= end.getY(); y++) { + for (int z = (int) start.getZ(); z <= end.getZ(); z++) { + Location loc = new Location(start.getWorld(), (double) x, (double) y, (double) z); + transmuteBlock(a, fromData, b, toData, loc, playerName, charge); + try { + Thread.sleep(rate); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + else { + for (int x = (int) start.getX(); x >= end.getX(); x--) { + for (int y = (int) start.getY(); y <= end.getY(); y++) { + for (int z = (int) start.getZ(); z >= end.getZ(); z--) { + Location loc = new Location(start.getWorld(), (double) x, (double) y, (double) z); + transmuteBlock(a, fromData, b, toData, loc, playerName, charge); + try { + Thread.sleep(rate); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + } + } + } + + public void transmuteBlock(final Material a, final byte fromData, final Material b, final byte toData, + final Location startBlockLoc, final String playerName, final boolean charge) { + + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + public void run() { + Player player = plugin.getServer().getPlayer(playerName); + Block startBlock = startBlockLoc.getBlock(); + double pay = GeometricMagicPlayerListener.calculatePay(a, fromData, b, toData, player); + + // exempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.exemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.exemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.exemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.exemptPlayer(player, CheckType.NO_SWING); + } + + if (player != null) { + if (startBlock.getType() == a && startBlock.getData() == fromData) { + + if (-1 * GeometricMagicPlayerListener.getBalance(player) < pay || !charge) { + + // Block break + if (a != Material.AIR && b == Material.AIR) { + + if (!GeometricMagicPlayerListener.checkBreakBlacklist(a.getId())) { + + Location blockLocation = startBlock.getLocation(); + + if (GeometricMagicPlayerListener.checkBlockBreakSimulation(blockLocation, player)) { + // Change block + startBlock.setType(b); + if (toData != 0) + startBlock.setData(toData); + + if (charge) { + if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + + Economy econ = GeometricMagic.getEconomy(); + + // Deposit or withdraw to players Vault account + if (pay > 0) { + econ.depositPlayer(player.getName(), pay); + } else if (pay < 0) { + econ.withdrawPlayer(player.getName(), pay * -1); + } + } else if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + player.setLevel((int) (player.getLevel() + pay)); + } + } + } + } + + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + return; + } + } + + // Block place + else if (a == Material.AIR && b != Material.AIR) { + + if (!GeometricMagicPlayerListener.checkPlaceBlacklist(b.getId())) { + + Location blockLocation = startBlock.getLocation(); + int blockID = b.getId(); + byte blockData = toData; + + if (GeometricMagicPlayerListener.checkBlockPlaceSimulation(blockLocation, blockID, blockData, blockLocation, player)) { + // Change block + startBlock.setType(b); + if (toData != 0) + startBlock.setData(toData); + + if (charge) { + if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + + Economy econ = GeometricMagic.getEconomy(); + + // Deposit or withdraw to players Vault account + if (pay > 0) { + econ.depositPlayer(player.getName(), pay); + } else if (pay < 0) { + econ.withdrawPlayer(player.getName(), pay * -1); + } + } else if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + player.setLevel((int) (player.getLevel() + pay)); + } + } + } + } + + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + return; + } + } + + // Block break and place + else if (a != Material.AIR && b != Material.AIR) { + + if (!GeometricMagicPlayerListener.checkBreakBlacklist(a.getId()) && !GeometricMagicPlayerListener.checkPlaceBlacklist(b.getId())) { + + Location blockLocation = startBlock.getLocation(); + int blockID = b.getId(); + byte blockData = toData; + + if (GeometricMagicPlayerListener.checkBlockBreakSimulation(blockLocation, player) + && GeometricMagicPlayerListener.checkBlockPlaceSimulation(blockLocation, blockID, blockData, blockLocation, player)) { + // Change block + startBlock.setType(b); + if (toData != 0) + startBlock.setData(toData); + + if (charge) { + if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("vault")) { + + Economy econ = GeometricMagic.getEconomy(); + + // Deposit or withdraw to players Vault account + if (pay > 0) { + econ.depositPlayer(player.getName(), pay); + } else if (pay < 0) { + econ.withdrawPlayer(player.getName(), pay * -1); + } + } else if (GeometricMagicPlayerListener.getTransmutationCostSystem(plugin).equalsIgnoreCase("xp")) { + player.setLevel((int) (player.getLevel() + pay)); + } + } + } + } + + else { + player.sendMessage(ChatColor.RED + "[GeometricMagic] That block is blacklisted"); + return; + } + + } + } else { + player.sendMessage(ChatColor.RED + "You do not have enough power to create that block"); + return; + } + } else + // System.out.println("[GeometricMagic] DEBUG - Block Data: " + (int) startBlock.getData() + ", A Data: " + (int) fromData + ", B Data: " + (int) toData); + return; + } + + // unexempt player from AntiCheat check + if (Bukkit.getServer().getPluginManager().getPlugin("AntiCheat") != null) { + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_PLACE); + AnticheatAPI.unexemptPlayer(player, CheckType.FAST_BREAK); + AnticheatAPI.unexemptPlayer(player, CheckType.LONG_REACH); + AnticheatAPI.unexemptPlayer(player, CheckType.NO_SWING); + } + } + }, 0L); + } +} \ No newline at end of file diff --git a/src/me/cakenggt/GeometricMagic/Metrics.java b/src/me/cakenggt/GeometricMagic/Metrics.java new file mode 100644 index 0000000..0f10dc1 --- /dev/null +++ b/src/me/cakenggt/GeometricMagic/Metrics.java @@ -0,0 +1,607 @@ +/** + * GeometricMagic allows players to draw redstone circles on the ground to do things such as teleport and transmute blocks. + * Copyright (C) 2012 Alec Cox (cakenggt), Andrew Stevanus (Hoot215) + * + * 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 . + */ + +package me.cakenggt.GeometricMagic; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; +import java.util.logging.Level; + +/** + *

+ * The metrics class obtains data about a plugin and submits statistics about it to the metrics backend. + *

+ *

+ * Public methods provided by this class: + *

+ * + * Graph createGraph(String name);
+ * void addCustomData(Metrics.Plotter plotter);
+ * void start();
+ *
+ */ +public class Metrics { + + /** + * The current revision number + */ + private final static int REVISION = 5; + + /** + * The base url of the metrics domain + */ + private static final String BASE_URL = "http://mcstats.org"; + + /** + * The url used to report a server's status + */ + private static final String REPORT_URL = "/report/%s"; + + /** + * The file where guid and opt out is stored in + */ + private static final String CONFIG_FILE = "plugins/PluginMetrics/config.yml"; + + /** + * The separator to use for custom data. This MUST NOT change unless you are hosting your own + * version of metrics and want to change it. + */ + private static final String CUSTOM_DATA_SEPARATOR = "~~"; + + /** + * Interval of time to ping (in minutes) + */ + private static final int PING_INTERVAL = 10; + + /** + * The plugin this metrics submits for + */ + private final Plugin plugin; + + /** + * All of the custom graphs to submit to metrics + */ + private final Set graphs = Collections.synchronizedSet(new HashSet()); + + /** + * The default graph, used for addCustomData when you don't want a specific graph + */ + private final Graph defaultGraph = new Graph("Default"); + + /** + * The plugin configuration file + */ + private final YamlConfiguration configuration; + + /** + * The plugin configuration file + */ + private final File configurationFile; + + /** + * Unique server id + */ + private final String guid; + + /** + * Lock for synchronization + */ + private final Object optOutLock = new Object(); + + /** + * Id of the scheduled task + */ + private volatile int taskId = -1; + + public Metrics(final Plugin plugin) throws IOException { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + + this.plugin = plugin; + + // load the config + configurationFile = new File(CONFIG_FILE); + configuration = YamlConfiguration.loadConfiguration(configurationFile); + + // add some defaults + configuration.addDefault("opt-out", false); + configuration.addDefault("guid", UUID.randomUUID().toString()); + + // Do we need to create the file? + if (configuration.get("guid", null) == null) { + configuration.options().header("http://mcstats.org").copyDefaults(true); + configuration.save(configurationFile); + } + + // Load the guid then + guid = configuration.getString("guid"); + } + + /** + * Construct and create a Graph that can be used to separate specific plotters to their own graphs + * on the metrics website. Plotters can be added to the graph object returned. + * + * @param name + * @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given + */ + public Graph createGraph(final String name) { + if (name == null) { + throw new IllegalArgumentException("Graph name cannot be null"); + } + + // Construct the graph object + final Graph graph = new Graph(name); + + // Now we can add our graph + graphs.add(graph); + + // and return back + return graph; + } + + /** + * Add a Graph object to Metrics that represents data for the plugin that should be sent to the backend + * + * @param graph + */ + public void addGraph(final Graph graph) { + if (graph == null) { + throw new IllegalArgumentException("Graph cannot be null"); + } + + graphs.add(graph); + } + + /** + * Adds a custom data plotter to the default graph + * + * @param plotter + */ + public void addCustomData(final Plotter plotter) { + if (plotter == null) { + throw new IllegalArgumentException("Plotter cannot be null"); + } + + // Add the plotter to the graph o/ + defaultGraph.addPlotter(plotter); + + // Ensure the default graph is included in the submitted graphs + graphs.add(defaultGraph); + } + + /** + * Start measuring statistics. This will immediately create an async repeating task as the plugin and send + * the initial data to the metrics backend, and then after that it will post in increments of + * PING_INTERVAL * 1200 ticks. + * + * @return True if statistics measuring is running, otherwise false. + */ + public boolean start() { + synchronized (optOutLock) { + // Did we opt out? + if (isOptOut()) { + return false; + } + + // Is metrics already running? + if (taskId >= 0) { + return true; + } + + // Begin hitting the server with glorious data + taskId = plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable() { + + private boolean firstPost = true; + + public void run() { + try { + // This has to be synchronized or it can collide with the disable method. + synchronized (optOutLock) { + // Disable Task, if it is running and the server owner decided to opt-out + if (isOptOut() && taskId > 0) { + plugin.getServer().getScheduler().cancelTask(taskId); + taskId = -1; + // Tell all plotters to stop gathering information. + for (Graph graph : graphs){ + graph.onOptOut(); + } + } + } + + // We use the inverse of firstPost because if it is the first time we are posting, + // it is not a interval ping, so it evaluates to FALSE + // Each time thereafter it will evaluate to TRUE, i.e PING! + postPlugin(!firstPost); + + // After the first post we set firstPost to false + // Each post thereafter will be a ping + firstPost = false; + } catch (IOException e) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage()); + } + } + }, 0, PING_INTERVAL * 1200); + + return true; + } + } + + /** + * Has the server owner denied plugin metrics? + * + * @return + */ + public boolean isOptOut() { + synchronized(optOutLock) { + try { + // Reload the metrics file + configuration.load(CONFIG_FILE); + } catch (IOException ex) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + return true; + } catch (InvalidConfigurationException ex) { + Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage()); + return true; + } + return configuration.getBoolean("opt-out", false); + } + } + + /** + * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. + * + * @throws IOException + */ + public void enable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (isOptOut()) { + configuration.set("opt-out", false); + configuration.save(configurationFile); + } + + // Enable Task, if it is not running + if (taskId < 0) { + start(); + } + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + * @throws IOException + */ + public void disable() throws IOException { + // This has to be synchronized or it can collide with the check in the task. + synchronized (optOutLock) { + // Check if the server owner has already set opt-out, if not, set it. + if (!isOptOut()) { + configuration.set("opt-out", true); + configuration.save(configurationFile); + } + + // Disable Task, if it is running + if (taskId > 0) { + this.plugin.getServer().getScheduler().cancelTask(taskId); + taskId = -1; + } + } + } + + /** + * Generic method that posts a plugin to the metrics website + */ + private void postPlugin(final boolean isPing) throws IOException { + // The plugin's description file containg all of the plugin data such as name, version, author, etc + final PluginDescriptionFile description = plugin.getDescription(); + + // Construct the post data + final StringBuilder data = new StringBuilder(); + data.append(encode("guid")).append('=').append(encode(guid)); + encodeDataPair(data, "version", description.getVersion()); + encodeDataPair(data, "server", Bukkit.getVersion()); + encodeDataPair(data, "players", Integer.toString(Bukkit.getServer().getOnlinePlayers().length)); + encodeDataPair(data, "revision", String.valueOf(REVISION)); + + // If we're pinging, append it + if (isPing) { + encodeDataPair(data, "ping", "true"); + } + + // Acquire a lock on the graphs, which lets us make the assumption we also lock everything + // inside of the graph (e.g plotters) + synchronized (graphs) { + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) { + final Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) { + // The key name to send to the metrics server + // The format is C-GRAPHNAME-PLOTTERNAME where separator - is defined at the top + // Legacy (R4) submitters use the format Custom%s, or CustomPLOTTERNAME + final String key = String.format("C%s%s%s%s", CUSTOM_DATA_SEPARATOR, graph.getName(), CUSTOM_DATA_SEPARATOR, plotter.getColumnName()); + + // The value to send, which for the foreseeable future is just the string + // value of plotter.getValue() + final String value = Integer.toString(plotter.getValue()); + + // Add it to the http post data :) + encodeDataPair(data, key, value); + } + } + } + + // Create the url + URL url = new URL(BASE_URL + String.format(REPORT_URL, encode(plugin.getDescription().getName()))); + + // Connect to the website + URLConnection connection; + + // Mineshafter creates a socks proxy, so we can safely bypass it + // It does not reroute POST requests so we need to go around it + if (isMineshafterPresent()) { + connection = url.openConnection(Proxy.NO_PROXY); + } else { + connection = url.openConnection(); + } + + connection.setDoOutput(true); + + // Write the data + final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); + writer.write(data.toString()); + writer.flush(); + + // Now read the response + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + final String response = reader.readLine(); + + // close resources + writer.close(); + reader.close(); + + if (response == null || response.startsWith("ERR")) { + throw new IOException(response); //Throw the exception + } else { + // Is this the first update this hour? + if (response.contains("OK This is your first update this hour")) { + synchronized (graphs) { + final Iterator iter = graphs.iterator(); + + while (iter.hasNext()) { + final Graph graph = iter.next(); + + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } + } + } + } + } + } + + /** + * Check if mineshafter is present. If it is, we need to bypass it to send POST requests + * + * @return + */ + private boolean isMineshafterPresent() { + try { + Class.forName("mineshafter.MineServer"); + return true; + } catch (Exception e) { + return false; + } + } + + /** + *

Encode a key/value data pair to be used in a HTTP post request. This INCLUDES a & so the first + * key/value pair MUST be included manually, e.g:

+ * + * StringBuffer data = new StringBuffer(); + * data.append(encode("guid")).append('=').append(encode(guid)); + * encodeDataPair(data, "version", description.getVersion()); + * + * + * @param buffer + * @param key + * @param value + * @return + */ + private static void encodeDataPair(final StringBuilder buffer, final String key, final String value) throws UnsupportedEncodingException { + buffer.append('&').append(encode(key)).append('=').append(encode(value)); + } + + /** + * Encode text as UTF-8 + * + * @param text + * @return + */ + private static String encode(final String text) throws UnsupportedEncodingException { + return URLEncoder.encode(text, "UTF-8"); + } + + /** + * Represents a custom graph on the website + */ + public static class Graph { + + /** + * The graph's name, alphanumeric and spaces only :) + * If it does not comply to the above when submitted, it is rejected + */ + private final String name; + + /** + * The set of plotters that are contained within this graph + */ + private final Set plotters = new LinkedHashSet(); + + private Graph(final String name) { + this.name = name; + } + + /** + * Gets the graph's name + * + * @return + */ + public String getName() { + return name; + } + + /** + * Add a plotter to the graph, which will be used to plot entries + * + * @param plotter + */ + public void addPlotter(final Plotter plotter) { + plotters.add(plotter); + } + + /** + * Remove a plotter from the graph + * + * @param plotter + */ + public void removePlotter(final Plotter plotter) { + plotters.remove(plotter); + } + + /** + * Gets an unmodifiable set of the plotter objects in the graph + * + * @return + */ + public Set getPlotters() { + return Collections.unmodifiableSet(plotters); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Graph)) { + return false; + } + + final Graph graph = (Graph) object; + return graph.name.equals(name); + } + + /** + * Called when the server owner decides to opt-out of Metrics while the server is running. + */ + protected void onOptOut(){} + + } + + /** + * Interface used to collect custom data for a plugin + */ + public static abstract class Plotter { + + /** + * The plot's name + */ + private final String name; + + /** + * Construct a plotter with the default plot name + */ + public Plotter() { + this("Default"); + } + + /** + * Construct a plotter with a specific plot name + * + * @param name + */ + public Plotter(final String name) { + this.name = name; + } + + /** + * Get the current value for the plotted point + * + * @return + */ + public abstract int getValue(); + + /** + * Get the column name for the plotted point + * + * @return the plotted point's column name + */ + public String getColumnName() { + return name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode(); + } + + @Override + public boolean equals(final Object object) { + if (!(object instanceof Plotter)) { + return false; + } + + final Plotter plotter = (Plotter) object; + return plotter.name.equals(name) && plotter.getValue() == getValue(); + } + + } + +} \ No newline at end of file