diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..def9802e8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/.idea/
+/.gradle/
+/testbed/
+/build/
diff --git a/.idea/libraries/Maven__org_bukkit_bukkit_1_12_2_R0_1_SNAPSHOT.xml b/.idea/libraries/Maven__org_bukkit_bukkit_1_12_2_R0_1_SNAPSHOT.xml
deleted file mode 100644
index 49760b2e5..000000000
--- a/.idea/libraries/Maven__org_bukkit_bukkit_1_12_2_R0_1_SNAPSHOT.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_spigotmc_spigot_api_1_12_2_R0_1_SNAPSHOT.xml b/.idea/libraries/Maven__org_spigotmc_spigot_api_1_12_2_R0_1_SNAPSHOT.xml
deleted file mode 100644
index 42f0d6f90..000000000
--- a/.idea/libraries/Maven__org_spigotmc_spigot_api_1_12_2_R0_1_SNAPSHOT.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_yaml_snakeyaml_1_19.xml b/.idea/libraries/Maven__org_yaml_snakeyaml_1_19.xml
deleted file mode 100644
index 33ccf19e2..000000000
--- a/.idea/libraries/Maven__org_yaml_snakeyaml_1_19.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/README.md b/README.md
index 83b5dcc7f..1d9ad7858 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,126 @@
-# EliteMobs
+Thank you for using EliteMobs!
-This is the GitHub project for the Minecraft plugin EliteMobs (Spigot page can be seen here: https://www.spigotmc.org/resources/elitemobs.40090/)
+This plugin is made to both work from the very start with no additional config work and to be highly customizable.
-Feel free to check the source code and do any edits you might deem necessary for your own servers.
+If you want to make some deep configuration changes to the plugin, try to read the GitHub wiki I've created ahead of time or as you're making the changes so you know what the options are doing. https://github.com/MagmaGuy/EliteMobs
-At this time, I am not interested in accepting contributions to the code. This is my first project of this dimension, and I'd like to have all components of it be written by me.
+If you need support with this plugin, you can reach me at my discord support channel: https://discord.gg/QSA2wgh
-That being said, I am deeply interested in any suggestions, be they for improving existing features or creating new ones.
+For all things EliteMobs related, you can go to my website to find all resources I've made available, such as the github page, the wiki, the custom loot maker, so on.
-# There's a wiki, it has a few entries, if you want more info maybe try reading it.
+Hope you enjoy! If you do, leave rating on the resource page and / or buy me a coffee ! (paypal links can be found in the spigot resource page)
-# //TODO: add description of features and how they work, some day, maybe
\ No newline at end of file
+
+# Dev notes:
+
+## API
+
+EliteMobs has a few basic APIs to interface with in the `com.magmaguy.elitemobs.api` package. Here's the breakdown:
+
+### DamageEliteMob
+
+Used for applying custom damage to Elite Mobs. Uses:
+- Bypass EliteMobs' custom damage system for a specific damage event
+- Apply an automatically recommended custom amount of damage which varies based on the tier of the boss.
+
+*Note:* the variable damage takes the elite's tier into account and deals more damage to higher tiers. It does not take the health multiplier into account for custom bosses for balance reasons.
+
+### EliteMobDamagedByEliteMobEvent
+
+Used for listening to moments when one Elite damages another Elite. Uses:
+- Same as Bukkit's EntityDamagedByEntity event but for elites specifically
+- Cancelling it might not work. Report if it doesn't.
+
+### EliteMobDamagedByPlayerAntiExploit
+Used for listening to events which trigger an antiexploit **check** - doesn't necessarily mean that it detected an exploit. Uses:
+- Same as Bukkit's EntityDamagedByEntity event but for elites specifically
+- Can be cancelled
+
+### EliteMobDamagedByPlayerEvent:
+Used for listening to moments when a player damages an Elite. Uses:
+
+- Same as Bukkit's EntityDamagedByEntity event but for players damaging elites specifically
+- ***Important:*** can't be cancelled as it only fires after applying the damage
+
+### EliteMobDamagedEvent:
+Used for listening to moments when an elite is damaged in general. Uses:
+
+- Same as Bukkit's EntityDamageEvent
+- ***Important*** Cancelling this event might not 100% work, report if it doesn't
+
+### EliteMobDeathEvent:
+Used to listening to moments when an elite is killed. Uses:
+
+- Same as Bukkit's EntityDeathEvent.
+
+### EliteMobEnterCombatEvent:
+Used for listening to moments when an elite enters combat against a player. Uses:
+
+- Get the target (player only) of the Elite
+- Get the elite which entered in combat
+
+#### EliteMobExitCombatEvent:
+Used for listening to moments when an elite leaves combat against a player. Uses:
+
+- Get the elite which just let combat.
+
+### EliteMobsItemDetector:
+Used for detecting whether an ItemStack is an EliteMobs ItemStack (like a custom item or a procedurally generated item). Uses:
+
+- Detect if an ItemStack is an EliteMobs custom or dynamic item.
+
+### EliteMobSpawnEvent:
+Used for detecting when an Elite spawns. USes:
+
+- Detect when an Elite spawns
+- Detect which Elite spawned
+
+### EliteMobTargetPlayerEvent:
+Used for detecting when an Elite has targetted a player. Uses:
+
+- Detect when an Elite targets a player.
+- Cancel an Elite's detection of a player.
+
+### GenericAntiExploitEvent
+
+Used for listening to moments when the antiexploit runs a check but no players damaged it. Uses:
+
+- Detect when the antiexploit is doing a non-player based exploit check
+- Cancel an antiexploit check
+
+### PlayerDamagedByEliteMobEvent
+
+Used for listening to moments when players are damaged by an Elite. Uses:
+
+- Same as Bukkit's EntityDamageEvent
+
+---
+
+
+## To add new item enchantments:
+1) Add new enchantment class to the `com.magmaguy.elitemobs.config.enchantments.premade` **extending** `EnchantmentsConfigFields` to initialize create its config file (naming convention: [EnchantmentName]Config)
+2) Initialize enchantment in `CustomEnchantment` to initialize the config file
+3) Add enchantment class to `com.magmaguy.elitemobs.items.customenchantments` **extending** `CustomEnchantment` to write the logic for the enchantment (naming convention [EnchantmentName]Enchantment)
+4) Add a public static String called "key" to register using the ItemTagger class for persistent enchantment tracking
+5) Add an customLootEntry to the parseEnchantments() method in `CustomItem` so custom items detect it correctly
+6) (Alternative) Add an customLootEntry to `generateCustomEnchantments()` method in `EnchantmentGenerator` if the enchantment should appear in procedurally generated items
+
+Note:
+- Don't forget to register events in `EventsRegistrer` if the part with logic in it requires events.
+- Don't forget to use the damage bypass if the power is supposed to deal custom damage. Damage dealt by the player to an elite can be overwritten in `CombatSystem` through the static "bypass" boolean field - it makes the next damage dealt to the elite use the raw damage value. For correctly assigning damage, use Bukkit's `Damageable#damage(double amount, Entity source)` and assign the source to your player.
+
+## To add new powers to elites:
+
+to be documented
+
+## To add new events:
+
+to be documented
+
+## To add new default NPCs:
+
+to be documented
+
+## To add new mob types:
+
+to be documented
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 000000000..b74b62e05
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,166 @@
+plugins {
+ id 'java-library'
+ id 'idea'
+ id 'maven-publish'
+ id "com.github.johnrengelman.shadow" version "7.0.0"
+}
+
+//Fixes issues related to special characters being used
+compileJava.options.encoding = "UTF-8"
+compileTestJava.options.encoding = "UTF-8"
+
+group 'com.magmaguy'
+version '7.3.15-SNAPSHOT-5'
+
+repositories {
+ maven {
+ url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
+
+ // As of Gradle 5.1, you can limit this to only those
+ // dependencies you expect from it
+ content {
+ includeGroup 'org.bukkit'
+ includeGroup 'org.spigotmc'
+ }
+ }
+
+ mavenCentral()
+ jcenter()
+ mavenLocal()
+
+ //Spigot API & CloudCommands
+ maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' }
+ maven { url = 'https://oss.sonatype.org/content/repositories/central' }
+
+ maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots" }
+
+ //Bstats API
+ maven { url = 'https://repo.codemc.org/repository/maven-public' }
+ //CloudCommands
+ maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' }
+ //Vault
+ maven { url = 'https://jitpack.io' }
+ //DiscordSRV
+ maven { url = 'https://m2.dv8tion.net/releases/' }
+ maven { url = 'https://nexus.scarsz.me/content/groups/public/' }
+ //LibsDisguises
+ maven { url = 'https://repo.md-5.net/content/groups/public/' }
+ //PlaceholderAPI
+ maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
+
+ //WorldGuard API
+ maven { url = 'https://maven.enginehub.org/repo/' }
+
+ //Model Engine
+ maven {
+ url = 'https://mvn.lumine.io/repository/maven-public/'
+ metadataSources {
+ artifact()
+ }
+ }
+
+ //Geyser
+ maven { url = 'https://repo.opencollab.dev/main/' }
+
+}
+
+dependencies {
+ //Spigot API
+ compileOnly "org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT"
+
+ //compileOnly 'org.spigotmc:spigot:1.17-R0.1-SNAPSHOT'
+ // The full CraftBukkit server with no shadowing. Requires mavenLocal.
+ //BStats API
+ implementation group: 'org.bstats', name: 'bstats-bukkit', version: '2.2.1'
+ //WorldGuard API
+ compileOnly group: 'com.sk89q.worldguard', name: 'worldguard-bukkit', version: '7.0.0'
+ //CloudCommands
+ implementation group: 'cloud.commandframework', name: 'cloud-paper', version: '1.5.0'
+ //CloudCommands Minecraft Extras module
+ implementation group: 'cloud.commandframework', name: 'cloud-minecraft-extras', version: '1.5.0'
+ //CloudCommands Adventure Platform module
+ implementation("net.kyori:adventure-platform-bukkit:4.0.0")
+ //I can't remember what this was for but it's in CloudCommands
+ implementation group: 'io.leangen.geantyref', name: 'geantyref', version: '1.3.4'
+ //Vault
+ //compileOnly group: 'com.github.MilkBowl', name: 'VaultAPI', version: '1.7'
+ compileOnly("com.github.MilkBowl:VaultAPI:1.7") {
+ exclude group: 'org.bukkit', module: 'bukkit'
+ }
+ //DiscordSRV
+ //compileOnly 'net.dv8tion:JDA:4.2.1_262'
+ compileOnly 'com.discordsrv:discordsrv:1.24.0'
+ //SQLite
+ compileOnly group: 'org.xerial', name: 'sqlite-jdbc', version: '3.32.3'
+ //LibsDisguises
+ compileOnly group: 'com.comphenix.protocol', name: 'ProtocolLib', version: '4.7.0';
+ compileOnly group: 'LibsDisguises', name: 'LibsDisguises', version: '10.0.26'
+ //PlaceholderAPI
+ compileOnly group: 'me.clip', name: 'placeholderapi', version: '2.10.9'
+
+ implementation group: 'commons-io', name: 'commons-io', version: '2.6'
+
+ //reflections - used for config initialization
+ implementation group: 'org.reflections', name: 'reflections', version: '0.9.12'
+
+ //lombok
+ compileOnly 'org.projectlombok:lombok:1.18.22'
+ annotationProcessor 'org.projectlombok:lombok:1.18.22'
+
+ //Model Engine
+ compileOnly "com.ticxo.modelengine:api:R2.5.0"
+
+ testCompileOnly 'org.projectlombok:lombok:1.18.20'
+ testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
+
+ //Geyser for bedrock player detection
+ //This needs java 16 to work so you will want to change gradle.properties to match your directory for it
+ //compileOnly("org.geysermc:geyser-api:2.0.2-SNAPSHOT") disabled because I couldn't find an easy way to see if a player is using geyser through their api due to the bungeecord / waterfall specific implementations
+
+}
+
+/*
+java {
+ toolchain {
+ languageVersion.set(JavaLanguageVersion.of(16))
+ }
+}
+ */
+
+artifacts { // task 'build' runs generates uberjar
+ archives shadowJar
+}
+
+jar {
+ archiveClassifier.set('min') // we want the Uberjar to be distributed, this is the minified version
+}
+
+String packagePath = 'com.magmaguy.shaded'
+
+// Relocating a Package
+shadowJar {
+ dependencies {
+ relocate('org.bstats', packagePath + '.bstats')
+ relocate('cloud.commandframework', packagePath + '.cloud')
+ relocate('net.kyori', packagePath + '.adventure-platform-bukkit')
+ relocate('io.leangen.geantyref', packagePath + '.geantyref')
+ relocate('org.reflections', packagePath + '.reflections')
+ }
+ archiveClassifier.set(null)
+ archiveFileName.set(project.name + ".jar")
+ destinationDirectory.set(new File("testbed/plugins"))
+}
+
+tasks.withType(JavaCompile) {
+ options.encoding = 'UTF-8'
+}
+
+ext {
+ resourceTokens = [
+ 'Version': version
+ ]
+}
+
+processResources {
+ filter org.apache.tools.ant.filters.ReplaceTokens, tokens: resourceTokens
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 000000000..e099597eb
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,5 @@
+projectName=EliteMobs
+group=com.magmaguy.elitemobs
+version=7.2.33
+author=MagmaGuy
+mainClass=EliteMobs
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..e708b1c02
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..f371643ee
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index e9421a232..000000000
--- a/pom.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-
- 4.0.0
-
- com.magmaguy
- EliteMobs
- 6.6.5
- jar
-
-
- UTF-8
-
-
-
- ${project.artifactId}
- clean resources:resources package
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.6.2
-
- 1.8
- 1.8
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.3
-
- false
-
-
- org.bstats:*
-
-
-
-
- org.bstats
-
- com.magmaguy.elitemobs
-
-
-
-
-
- package
-
- shade
-
-
-
-
-
-
-
-
-
- spigotmc-repo
- https://hub.spigotmc.org/nexus/content/groups/public/
-
-
- bstats-repo
- http://repo.bstats.org/content/repositories/releases/
-
-
-
-
-
-
- org.spigotmc
- spigot-api
- 1.12.2-R0.1-SNAPSHOT
- provided
-
-
-
- org.bukkit
- bukkit
- 1.12.2-R0.1-SNAPSHOT
- provided
-
-
-
- org.bstats
- bstats-bukkit
- 1.1
-
-
-
-
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 000000000..b4b573413
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "EliteMobs"
\ No newline at end of file
diff --git a/src/main/java/com/magmaguy/elitemobs/ChatColorConverter.java b/src/main/java/com/magmaguy/elitemobs/ChatColorConverter.java
index 59721b1b2..14fdea1d8 100644
--- a/src/main/java/com/magmaguy/elitemobs/ChatColorConverter.java
+++ b/src/main/java/com/magmaguy/elitemobs/ChatColorConverter.java
@@ -1,31 +1,28 @@
-/*
- * 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 com.magmaguy.elitemobs;
import org.bukkit.ChatColor;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Created by MagmaGuy on 13/05/2017.
*/
public class ChatColorConverter {
- public static String convert(String string) {
+ private ChatColorConverter() {
+ }
+ public static String convert(String string) {
+ if (string == null) return "";
return ChatColor.translateAlternateColorCodes('&', string);
+ }
+ public static List convert(List list) {
+ List convertedList = new ArrayList<>();
+ for (String string : list)
+ convertedList.add(convert(string));
+ return convertedList;
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/CrashFix.java b/src/main/java/com/magmaguy/elitemobs/CrashFix.java
new file mode 100644
index 000000000..45845ee01
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/CrashFix.java
@@ -0,0 +1,79 @@
+package com.magmaguy.elitemobs;
+
+import com.magmaguy.elitemobs.utils.ChunkVectorizer;
+import com.magmaguy.elitemobs.utils.PersistentVanillaData;
+import org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.ChunkLoadEvent;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashSet;
+
+public class CrashFix implements Listener {
+
+ private static final HashSet temporarilyCachedChunks = new HashSet<>();
+ public static String key = "EliteMobsCullable";
+ public static HashSet knownSessionChunks = new HashSet<>();
+
+ public static void persistentTracker(Entity entity) {
+ PersistentVanillaData.write(entity, key, "delete_me");
+ }
+
+ public static boolean isPersistentEntity(Entity entity) {
+ return PersistentVanillaData.hasString(entity, key);
+ }
+
+ public static void startupCheck() {
+ for (World world : Bukkit.getWorlds())
+ for (Chunk chunk : world.getLoadedChunks()) {
+ chunkCheck(chunk);
+ knownSessionChunks.add(ChunkVectorizer.hash(chunk));
+ }
+ }
+
+ private static void chunkCheck(Chunk chunk) {
+ for (Entity entity : chunk.getEntities())
+ if (isPersistentEntity(entity))
+ entity.remove();
+ }
+
+ /**
+ * This runs during startup. There is currently an issue with entities not getting scanned correctly when the chunk
+ * loads, as well as an issue with double chunk loading. Additionally, since all elites are initialized during startup,
+ * delaying the chunk by 1 tick causes the valid entities to be deleted as soon as they load in. To fix this, entities
+ * that exist in a chunk when it is loaded are instead cached, and the chunk getting loaded is cached as well. The
+ * chunk cache prevents a double check from happening, and entity cache prevents the plugin from scanning entities
+ * other than the ones that persisted through a restart.
+ *
+ * @param chunk
+ */
+ private static void delayedChunkCheck(Chunk chunk, int hashedChunk) {
+ Entity[] entities = chunk.getEntities().clone();
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ for (Entity entity : entities)
+ if (isPersistentEntity(entity))
+ entity.remove();
+ temporarilyCachedChunks.remove(hashedChunk);
+ }
+ }.runTaskLater(MetadataHandler.PLUGIN, 1);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
+ public void onChunkLoad(ChunkLoadEvent event) {
+ int hashedChunk = ChunkVectorizer.hash(event.getChunk());
+ //For some reason there is double chunk loading going on, and entities aren't getting detected correctly
+ if (temporarilyCachedChunks.contains(hashedChunk)) return;
+ temporarilyCachedChunks.add(hashedChunk);
+ if (knownSessionChunks.contains(hashedChunk)) return;
+ knownSessionChunks.add(hashedChunk);
+ delayedChunkCheck(event.getChunk(), hashedChunk);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/EliteMobs.java b/src/main/java/com/magmaguy/elitemobs/EliteMobs.java
index 92a9358e3..fbea77666 100644
--- a/src/main/java/com/magmaguy/elitemobs/EliteMobs.java
+++ b/src/main/java/com/magmaguy/elitemobs/EliteMobs.java
@@ -4,61 +4,183 @@
* Created by MagmaGuy on 07/10/2016.
*/
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerEvent;
import com.magmaguy.elitemobs.commands.CommandHandler;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.DefaultConfig;
-import com.magmaguy.elitemobs.config.ValidMobsConfig;
-import com.magmaguy.elitemobs.events.EventLauncher;
-import com.magmaguy.elitemobs.items.CustomItemConstructor;
-import com.magmaguy.elitemobs.items.customenchantments.CustomEnchantmentCache;
-import com.magmaguy.elitemobs.items.uniqueitems.UniqueItemInitializer;
-import com.magmaguy.elitemobs.mobconstructor.CombatSystem;
+import com.magmaguy.elitemobs.commands.guild.AdventurersGuildCommand;
+import com.magmaguy.elitemobs.config.*;
+import com.magmaguy.elitemobs.config.commands.CommandsConfig;
+import com.magmaguy.elitemobs.config.customarenas.CustomArenasConfig;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfig;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields;
+import com.magmaguy.elitemobs.config.customevents.CustomEventsConfig;
+import com.magmaguy.elitemobs.config.customitems.CustomItemsConfig;
+import com.magmaguy.elitemobs.config.customquests.CustomQuestsConfig;
+import com.magmaguy.elitemobs.config.customspawns.CustomSpawnConfig;
+import com.magmaguy.elitemobs.config.customtreasurechests.CustomTreasureChestsConfig;
+import com.magmaguy.elitemobs.config.dungeonpackager.DungeonPackagerConfig;
+import com.magmaguy.elitemobs.config.dungeonpackager.DungeonPackagerConfigFields;
+import com.magmaguy.elitemobs.config.enchantments.EnchantmentsConfig;
+import com.magmaguy.elitemobs.config.menus.MenusConfig;
+import com.magmaguy.elitemobs.config.mobproperties.MobPropertiesConfig;
+import com.magmaguy.elitemobs.config.npcs.NPCsConfig;
+import com.magmaguy.elitemobs.config.potioneffects.PotionEffectsConfig;
+import com.magmaguy.elitemobs.config.powers.PowersConfig;
+import com.magmaguy.elitemobs.config.wormholes.WormholeConfig;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.economy.VaultCompatibility;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.events.ActionEvent;
+import com.magmaguy.elitemobs.events.TimedEvent;
+import com.magmaguy.elitemobs.explosionregen.Explosion;
+import com.magmaguy.elitemobs.gamemodes.nightmaremodeworld.DaylightWatchdog;
+import com.magmaguy.elitemobs.gamemodes.zoneworld.Grid;
+import com.magmaguy.elitemobs.instanced.MatchInstance;
+import com.magmaguy.elitemobs.items.LootTables;
+import com.magmaguy.elitemobs.items.customenchantments.CustomEnchantment;
+import com.magmaguy.elitemobs.items.customitems.CustomItem;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.RegionalBossEntity;
import com.magmaguy.elitemobs.mobconstructor.mobdata.PluginMobProperties;
-import com.magmaguy.elitemobs.mobpowers.majorpowers.SkeletonTrackingArrow;
-import com.magmaguy.elitemobs.playerdata.PlayerData;
+import com.magmaguy.elitemobs.mobs.passive.EggRunnable;
+import com.magmaguy.elitemobs.mobs.passive.PassiveEliteMobDeathHandler;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
import com.magmaguy.elitemobs.powerstances.MajorPowerStanceMath;
import com.magmaguy.elitemobs.powerstances.MinorPowerStanceMath;
-import com.magmaguy.elitemobs.runnables.*;
+import com.magmaguy.elitemobs.quests.QuestTracking;
+import com.magmaguy.elitemobs.thirdparty.bstats.CustomCharts;
+import com.magmaguy.elitemobs.thirdparty.libsdisguises.DisguiseEntity;
+import com.magmaguy.elitemobs.thirdparty.placeholderapi.Placeholders;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility;
+import com.magmaguy.elitemobs.treasurechest.TreasureChest;
+import com.magmaguy.elitemobs.utils.InfoMessage;
+import com.magmaguy.elitemobs.utils.ServerTime;
+import com.magmaguy.elitemobs.utils.WarningMessage;
import com.magmaguy.elitemobs.versionnotifier.VersionChecker;
-import com.magmaguy.elitemobs.versionnotifier.VersionWarner;
-import org.bstats.Metrics;
+import com.magmaguy.elitemobs.worlds.CustomWorldLoading;
+import com.magmaguy.elitemobs.wormhole.Wormhole;
+import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.World;
-import org.bukkit.entity.Arrow;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.HandlerList;
import org.bukkit.plugin.java.JavaPlugin;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class EliteMobs extends JavaPlugin {
public static List validWorldList = new ArrayList();
+ public static boolean worldGuardIsEnabled = false;
+ public static List zoneBasedSpawningWorlds = new ArrayList<>();
+ public static List nightmareWorlds = new ArrayList<>();
+ public static Metrics metrics;
+ public Object placeholders = null;
+
+ public static void initializeConfigs() {
+ DefaultConfig.initializeConfig();
+ ItemSettingsConfig.initializeConfig();
+ ProceduralItemGenerationSettingsConfig.initializeConfig();
+ PotionEffectsConfig.initializeConfigs();
+ TranslationConfig.initializeConfig();
+ EconomySettingsConfig.initializeConfig();
+ EventsConfig.initializeConfig();
+ new EnchantmentsConfig();
+ AntiExploitConfig.initializeConfig();
+ CombatTagConfig.initializeConfig();
+ AntiExploitConfig.initializeConfig();
+ AdventurersGuildConfig.initializeConfig();
+ ValidWorldsConfig.initializeConfig();
+
+ new MenusConfig();
+ new PowersConfig();
+ MobPropertiesConfig.initializeConfigs();
+ CustomEnchantment.initializeCustomEnchantments();
+
+ MobCombatSettingsConfig.initializeConfig();
+ CommandsConfig.initializeConfigs();
+ DiscordSRVConfig.initializeConfig();
+ ReadMeForTranslationsConfig.initialize();
+ ItemUpgradeSystemConfig.initializeConfig();
+ new CustomEventsConfig();
+ QuestsConfig.initializeConfig();
+ WormholesConfig.initializeConfig();
+ ArenasConfig.initializeConfig();
+ }
+
+ public static void worldScanner() {
+ for (World world : Bukkit.getWorlds())
+ if (ValidWorldsConfig.getFileConfiguration().getBoolean("Valid worlds." + world.getName())) {
+ validWorldList.add(world);
+ if (ValidWorldsConfig.getZoneBasedWorlds().contains(world.getName()))
+ zoneBasedSpawningWorlds.add(world);
+ if (ValidWorldsConfig.getNightmareWorlds().contains(world.getName())) {
+ nightmareWorlds.add(world);
+ DaylightWatchdog.preventDaylight(world);
+ }
+ }
+
+ }
@Override
public void onEnable() {
- //Enable stats
- Metrics metrics = new Metrics(this);
+ Bukkit.getLogger().info(" _____ _ _____ _____ ________ ______________ _____");
+ Bukkit.getLogger().info("| ___| | |_ _|_ _| ___| \\/ | _ | ___ \\/ ___|");
+ Bukkit.getLogger().info("| |__ | | | | | | | |__ | . . | | | | |_/ /\\ `--.");
+ Bukkit.getLogger().info("| __|| | | | | | | __|| |\\/| | | | | ___ \\ `--. \\");
+ Bukkit.getLogger().info("| |___| |_____| |_ | | | |___| | | \\ \\_/ / |_/ //\\__/ /");
+ Bukkit.getLogger().info("\\____/\\_____/\\___/ \\_/ \\____/\\_| |_/\\___/\\____/ \\____/");
+ MetadataHandler.PLUGIN = this;
+ Bukkit.getLogger().info("By MagmaGuy - v. " + MetadataHandler.PLUGIN.getDescription().getVersion());
+
+ ServerTime.startTickCounter();
+
+ if (Bukkit.getServer().spigot().getConfig().getDouble("settings.attribute.maxHealth.max") < 100000000) {
+ Bukkit.getServer().spigot().getConfig().set("settings.attribute.maxHealth.max", 100000000);
+ try {
+ File spigotConfigContainer = new File(Paths.get(MetadataHandler.PLUGIN.getDataFolder().getParentFile().getCanonicalFile().getParentFile().toString() + "/spigot.yml").toString());
+ Bukkit.getServer().spigot().getConfig().save(spigotConfigContainer);
+ new InfoMessage("New default max health set correctly!");
+ } catch (IOException e) {
+ new WarningMessage("Failed to save max health value! For the plugin to work correctly, you should increase your max health on the spigot.yml config file to " + 100000000);
+ }
+ }
+
+ //Remove entities that should not exist
+ CrashFix.startupCheck();
- //Initialize custom enchantments
- CustomEnchantmentCache.initialize();
+ /*
+ New config loading
+ */
+ initializeConfigs();
- //Load loot from config
- ConfigValues.intializeConfigurations();
- ConfigValues.initializeCachedConfigurations();
+ if (Bukkit.getPluginManager().isPluginEnabled("LibsDisguises"))
+ DisguiseEntity.initialize();
- //Parse loot
- CustomItemConstructor superDrops = new CustomItemConstructor();
- superDrops.superDropParser();
+ if (worldGuardIsEnabled)
+ Bukkit.getLogger().info("[EliteMobs] WorldGuard compatibility is enabled!");
+ else
+ Bukkit.getLogger().warning("[EliteMobs] WorldGuard compatibility is not enabled!");
- UniqueItemInitializer.initialize();
+ //Enable Vault
+ try {
+ VaultCompatibility.vaultSetup();
+ } catch (Exception e) {
+ Bukkit.getLogger().warning("[EliteMobs] Something went wrong with the vault configuration - your Vault " +
+ "version is probably not compatible with this EliteMobs version. Please contact the dev about this error.");
+ VaultCompatibility.VAULT_ENABLED = false;
+ }
//Hook up all listeners, some depend on config
EventsRegistrer.registerEvents();
//Launch the local data cache
- PlayerData.initializePlayerData();
- PlayerData.synchronizeDatabases();
+ PlayerData.initializeDatabaseConnection();
+ ElitePlayerInventory.initialize();
//Get world list
worldScanner();
@@ -66,15 +188,12 @@ public void onEnable() {
//Start the repeating tasks such as scanners
launchRunnables();
- //Commands
- this.getCommand("elitemobs").setExecutor(new CommandHandler());
-
//launch events
- EventLauncher eventLauncher = new EventLauncher();
- eventLauncher.eventRepeatingTask();
+ ActionEvent.initializeBlueprintEvents();
+ TimedEvent.initializeBlueprintEvents();
//launch internal clock for attack cooldown
- CombatSystem.launchInternalClock();
+ EliteMobDamagedByPlayerEvent.EliteMobDamagedByPlayerEventFilter.launchInternalClock();
/*
Initialize mob values
@@ -88,68 +207,189 @@ public void onEnable() {
MajorPowerStanceMath.initializeVectorCache();
/*
- Check for new plugin version
+ Scan for loaded SuperMobs
*/
- VersionChecker.updateComparer();
- if (!VersionChecker.pluginIsUpToDate)
- this.getServer().getPluginManager().registerEvents(new VersionWarner(), this);
+ PassiveEliteMobDeathHandler.SuperMobScanner.scanSuperMobs();
- }
+ // Small check to make sure that PlaceholderAPI is installed
+ if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
+ Placeholders placeholders = new Placeholders();
+ placeholders.register();
+ this.placeholders = placeholders;
+ }
- @Override
- public void onDisable() {
+ //Enable stats
+ metrics = new Metrics(this, 1081);
+ //Initialize custom charts
+ new CustomCharts();
+
+ //Imports custom configurations and mindungeons from the import folder
+ ConfigurationImporter.initializeConfigs();
+ ConfigurationExporter.initializeConfigs();
+
+ //Import custom items after potentially importing new items
+ new CustomItemsConfig();
+ CustomItem.initializeCustomItems();
+ LootTables.initialize();
+
+ //Load minidungeons, most of all load the worlds of minidungeons
+ new DungeonPackagerConfig();
+ //Load Adventurer's Guild
+ if (AdventurersGuildConfig.isGuildWorldIsEnabled()) {
+ try {
+ CustomWorldLoading.startupWorldInitialization();
+ AdventurersGuildCommand.defineTeleportLocation();
+ if (AdventurersGuildConfig.getGuildWorldLocation() == null)
+ AdventurersGuildConfig.toggleGuildInstall();
+ } catch (Exception e) {
+ AdventurersGuildConfig.toggleGuildInstall();
+ new WarningMessage("Failed to initialize the Adventurer's Guild Hub! It is now disabled. You can try to" +
+ "reenable it in /em setup");
+ }
+ }
+
+ //Load all regional bosses
+ new CustomBossesConfig();
+ new CustomTreasureChestsConfig();
+
+ //Find the stats of bosses in minidungeons
+ for (Minidungeon minidungeon : Minidungeon.getMinidungeons().values()) {
+ if (minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType() != null)
+ if (minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType().equals(DungeonPackagerConfigFields.DungeonLocationType.WORLD))
+ minidungeon.quantifyWorldBosses();
+ else if (minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType().equals(DungeonPackagerConfigFields.DungeonLocationType.SCHEMATIC))
+ minidungeon.quantifySchematicBosses(false);
+ }
+
+ //Initialize npcs
+ new NPCsConfig();
+
+ //Initialize custom spawn methods, this runs late because it compares loaded worlds against worlds listed in the config
+ try {
+ new CustomSpawnConfig();
+ } catch (Exception ex) {
+ new WarningMessage("You are using a version of Spigot or a branch thereof (Paper, Purpur, so on) that is (probably) HORRIBLY outdated!" +
+ " This issue will probably be fixed if you update your server version to the latest patch of the version you are running.");
+ new WarningMessage(
+ " This does not mean that you have to update your Minecraft version, but it does mean you must update your server version to the latest patch" +
+ " available for that Minecraft version. Download from trustworthy sources, as if you download Spigot from some random website other than Spigot," +
+ " you are probably not getting the latest version (and also there's a high chance you'll get a virus).");
+ }
+
+ new CustomQuestsConfig();
+
+ new WormholeConfig();
- EntityTracker.shutdownPurger();
+ //Commands
+ new CommandHandler();
+
+ //Arenas
+ new CustomArenasConfig();
/*
- Flush lingering arrows from the arrow tracking power
+ Check for new plugin version or for dungeon updates
*/
- for (Arrow arrow : SkeletonTrackingArrow.trackingArrowList)
- arrow.remove();
- SkeletonTrackingArrow.trackingArrowList.clear();
-
- CustomItemConstructor.customItemList.clear();
- CustomItemConstructor.staticCustomItemHashMap.clear();
- CustomItemConstructor.dynamicRankedItemStacks.clear();
- UniqueItemInitializer.uniqueItemsList.clear();
- validWorldList.clear();
+ VersionChecker.check();
+ }
- //save cached data
- Bukkit.getScheduler().cancelTask(PlayerData.databaseSyncTaskID);
- Bukkit.getLogger().info("[EliteMobs] Saving EliteMobs databases...");
- PlayerData.saveDatabases();
- Bukkit.getLogger().info("[EliteMobs] All saved! Good night.");
- PlayerData.clearPlayerData();
+ @Override
+ public void onLoad() {
+ //WorldGuard hook
+ try {
+ worldGuardIsEnabled = WorldGuardCompatibility.initialize();
+ } catch (NoClassDefFoundError | IllegalStateException ex) {
+ Bukkit.getLogger().warning("[EliteMobs] Error loading WorldGuard. EliteMob-specific flags will not work." +
+ " Except if you just reloaded the plugin, in which case they will totally work.");
+ worldGuardIsEnabled = false;
+ }
+ if (!worldGuardIsEnabled)
+ if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null)
+ worldGuardIsEnabled = true;
}
- public void worldScanner() {
+ @Override
+ public void onDisable() {
- for (World world : Bukkit.getWorlds())
- if (ConfigValues.validWorldsConfig.getBoolean("Valid worlds." + world.getName()))
- validWorldList.add(world);
+ new InfoMessage("Starting EliteMobs shutdown sequence...");
+
+ new InfoMessage("Regenerating exploded blocks...");
+ Explosion.regenerateAllPendingBlocks();
+
+ new InfoMessage("Cancelling tasks...");
+ Bukkit.getServer().getScheduler().cancelTasks(MetadataHandler.PLUGIN);
+
+ new InfoMessage("Closing wormholes...");
+ Wormhole.shutdown();
+
+ new InfoMessage("Spinning Regional Bosses down...");
+ //save all pending respawns
+ RegionalBossEntity.save();
+ RegionalBossEntity.getTrackableCustomBosses().clear();
+ RegionalBossEntity.getRegionalBossEntitySet().clear();
+
+ new InfoMessage("Wiping Elite entities clean...");
+ EntityTracker.wipeShutdown();
+
+ new InfoMessage("Clearing events...");
+ TimedEvent.shutdown();
+ ActionEvent.shutdown();
+
+ new InfoMessage("Clearing valid worlds...");
+ validWorldList.clear();
+ new InfoMessage("Clearing zone based worlds...");
+ zoneBasedSpawningWorlds.clear();
+ new InfoMessage("Clearing config regional elites...");
+ CustomBossesConfigFields.getRegionalElites().clear();
+ new InfoMessage("Clearing custom enchantments...");
+ CustomEnchantment.getCustomEnchantments().clear();
+ new InfoMessage("Clearing custom items...");
+ CustomItem.getCustomItems().clear();
+ CustomItem.getCustomItemStackList().clear();
+ CustomItem.getCustomItemStackShopList().clear();
+ CustomItem.getLimitedItem().clear();
+ CustomItem.getScalableItems().clear();
+ CustomItem.getFixedItems().clear();
+ CustomItem.getTieredLoot().clear();
+ CustomItem.getWeighedFixedItems().clear();
+ new InfoMessage("Clearing Minidungeons...");
+ Minidungeon.getMinidungeons().clear();
+ RegionalBossEntity.regionalBossesShutdown();
+
+ new InfoMessage("Unregistering placeholders...");
+ if (this.placeholders != null)
+ ((Placeholders) placeholders).unregister();
+
+ new InfoMessage("Unregistering handlers...");
+ HandlerList.unregisterAll(MetadataHandler.PLUGIN);
+
+ new InfoMessage("Clearing Treasure Chests...");
+ TreasureChest.clearTreasureChests();
+
+ new InfoMessage("Untracking quests...");
+ QuestTracking.clear();
+
+ MatchInstance.shutdown();
+
+ //save cached data
+ Bukkit.getLogger().info("[EliteMobs] Saving EliteMobs databases...");
+ PlayerData.closeConnection();
+ Bukkit.getLogger().info("[EliteMobs] All done! Good night.");
}
/*
Repeating tasks that run as long as the server is on
*/
- public void launchRunnables() {
-
- int eggTimerInterval = 20 * 60 * 10 / ConfigValues.defaultConfig.getInt(DefaultConfig.SUPERMOB_STACK_AMOUNT);
-
- new EntityScanner().runTaskTimer(this, 20, 20 * 10);
- new PotionEffectApplier().runTaskTimer(this, 20, 20);
- if (ConfigValues.defaultConfig.getBoolean(DefaultConfig.ENABLE_POWER_SCOREBOARDS))
- new ScoreboardUpdater().runTaskTimer(this, 20, 20);
- if (ConfigValues.validMobsConfig.getBoolean(ValidMobsConfig.ALLOW_PASSIVE_SUPERMOBS) &&
- ConfigValues.validMobsConfig.getBoolean(ValidMobsConfig.CHICKEN) &&
- ConfigValues.defaultConfig.getInt(DefaultConfig.SUPERMOB_STACK_AMOUNT) > 0)
+ private void launchRunnables() {
+ if (!zoneBasedSpawningWorlds.isEmpty())
+ Grid.initializeGrid();
+ int eggTimerInterval = 20 * 60 * 10 / DefaultConfig.getSuperMobStackAmount();
+ if (MobPropertiesConfig.getMobProperties().get(EntityType.CHICKEN).isEnabled() && DefaultConfig.getSuperMobStackAmount() > 0) {
new EggRunnable().runTaskTimer(this, eggTimerInterval, eggTimerInterval);
- new DynamicLoreUpdater().runTaskTimer(this, 20, 20 * 2);
-// new ReapplyDisplayEffects().runTaskTimer(this, 20, 20);
-// EntityListUpdater.startUpdating();
-
+ }
+ //save regional bosses when the files update
+ RegionalBossEntity.regionalDataSaver();
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/EntityTracker.java b/src/main/java/com/magmaguy/elitemobs/EntityTracker.java
deleted file mode 100644
index 2f9f51790..000000000
--- a/src/main/java/com/magmaguy/elitemobs/EntityTracker.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package com.magmaguy.elitemobs;
-
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.DefaultConfig;
-import com.magmaguy.elitemobs.mobconstructor.EliteMobEntity;
-import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
-import com.magmaguy.elitemobs.mobconstructor.mobdata.passivemobs.SuperMobProperties;
-import com.magmaguy.elitemobs.mobpowers.ElitePower;
-import org.bukkit.entity.*;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.CreatureSpawnEvent;
-import org.bukkit.event.entity.EntityDeathEvent;
-import org.bukkit.event.world.ChunkUnloadEvent;
-import org.bukkit.scheduler.BukkitRunnable;
-
-import java.util.HashSet;
-import java.util.Iterator;
-
-public class EntityTracker implements Listener {
-
- /*
- These HashSets track basically everything for live plugin entities
- */
- private static HashSet superMobs = new HashSet<>();
- private static HashSet eliteMobs = new HashSet<>();
- private static HashSet eliteMobsLivingEntities = new HashSet<>();
-
- private static HashSet naturalEntities = new HashSet<>();
- private static HashSet armorStands = new HashSet<>();
- private static HashSet- itemVisualEffects = new HashSet<>();
-
- /*
- This HashSet shouldn't really be scanned during runtime for aside from the occasional updates, it mostly exists to
- cull entities once the server shuts down
- */
- private static HashSet cullablePluginEntities = new HashSet<>();
-
- /*
- Starts tracking elite mobs
- */
- public static void registerEliteMob(EliteMobEntity eliteMobEntity) {
- eliteMobs.add(eliteMobEntity);
- eliteMobsLivingEntities.add(eliteMobEntity.getLivingEntity());
- registerCullableEntity(eliteMobEntity.getLivingEntity());
- }
-
- /*
- Starts tracking super mob
- */
- public static void registerSuperMob(LivingEntity livingEntity) {
- if (!SuperMobProperties.isValidSuperMobType(livingEntity)) return;
- superMobs.add(livingEntity);
- }
-
- /*
- Registers mobs that spawn naturally, necessary for elite mob rewards
- */
- public static void registerNaturalEntity(LivingEntity entity) {
- if (!EliteMobProperties.isValidEliteMobType(entity)) return;
- naturalEntities.add(entity);
- }
-
-
- public static void registerArmorStands(ArmorStand armorStand) {
- armorStands.add(armorStand);
- registerCullableEntity(armorStand);
- }
-
- public static void registerItemVisualEffects(Item item) {
- itemVisualEffects.add(item);
- registerCullableEntity(item);
- }
-
- /*
- Starts tracking any entity generated or managed by EliteMobs, useful for when they need to be culled
- Does not include super mobs to avoid culling them by mistake
- */
- public static void registerCullableEntity(Entity entity) {
- cullablePluginEntities.add(entity);
- }
-
- public static void checkEntityState() {
-
- new BukkitRunnable() {
- @Override
- public void run() {
- new BukkitRunnable() {
- @Override
- public void run() {
- updateSuperMobs();
- updateEliteMobEntities();
- updateLivingEntities();
- updateCullables();
- updateAmorStands();
- updateItems();
- }
- }.runTaskAsynchronously(MetadataHandler.PLUGIN);
- }
- }.runTaskTimer(MetadataHandler.PLUGIN, 20 * 60 * 5, 20 * 60 * 5);
-
- }
-
- private static void updateSuperMobs() {
- Iterator iterator = superMobs.iterator();
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
- if (!entity.isValid())
- iterator.remove();
- }
- }
-
- private static void updateLivingEntities() {
- Iterator iterator = naturalEntities.iterator();
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
- if (!entity.isValid())
- iterator.remove();
- }
- }
-
- private static void updateEliteMobEntities() {
- Iterator iterator = eliteMobs.iterator();
- while (iterator.hasNext()) {
- Entity entity = ((EliteMobEntity) iterator.next()).getLivingEntity();
- if (entity.isDead() ||
- !entity.isValid() && ((LivingEntity) entity).getRemoveWhenFarAway())
- iterator.remove();
- }
- }
-
- private static void updateAmorStands() {
- Iterator iterator = armorStands.iterator();
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
- if (!entity.isValid())
- iterator.remove();
- }
- }
-
- private static void updateCullables() {
- Iterator iterator = cullablePluginEntities.iterator();
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
- if (!entity.isValid())
- iterator.remove();
- }
- }
-
- private static void updateItems() {
- Iterator iterator = itemVisualEffects.iterator();
- while (iterator.hasNext()) {
- Entity entity = (Entity) iterator.next();
- if (!entity.isValid())
- iterator.remove();
- }
- }
-
- public static boolean isSuperMob(Entity entity) {
- if (!SuperMobProperties.isValidSuperMobType(entity)) return false;
- return superMobs.contains(entity);
- }
-
- public static boolean isEliteMob(Entity entity) {
- if (!EliteMobProperties.isValidEliteMobType(entity)) return false;
- return eliteMobsLivingEntities.contains(entity);
- }
-
- public static EliteMobEntity getEliteMobEntity(Entity entity) {
- if (!EliteMobProperties.isValidEliteMobType(entity)) return null;
- for (EliteMobEntity eliteMobEntity : eliteMobs)
- if (eliteMobEntity.getLivingEntity().equals(entity))
- return eliteMobEntity;
- return null;
- }
-
- public static EliteMobEntity getAsyncEliteMobEntity(Entity entity) {
- if (!EliteMobProperties.isValidEliteMobType(entity)) return null;
- HashSet localEntities = (HashSet) eliteMobs.clone();
- for (EliteMobEntity eliteMobEntity : localEntities)
- if (eliteMobEntity.getLivingEntity().equals(entity))
- return eliteMobEntity;
- return null;
- }
-
- public static boolean isNaturalEntity(Entity entity) {
- if (!EliteMobProperties.isValidEliteMobType(entity)) return false;
- return naturalEntities.contains(entity);
- }
-
- public static boolean isItemVisualEffect(Entity entity) {
- return (itemVisualEffects.contains(entity));
- }
-
- public static boolean hasPower(ElitePower mobPower, Entity entity) {
- EliteMobEntity eliteMobEntity = getEliteMobEntity(entity);
- if (eliteMobEntity == null) return false;
- return eliteMobEntity.hasPower(mobPower);
- }
-
- public static boolean hasPower(ElitePower mobPower, EliteMobEntity eliteMobEntity) {
- if (eliteMobEntity == null) return false;
- return eliteMobEntity.hasPower(mobPower);
- }
-
- public static void unregisterCullableEntity(Entity entity) {
- cullablePluginEntities.remove(entity);
- }
-
- public static void unregisterItemEntity(Item item) {
- itemVisualEffects.remove(item);
- }
-
- /*
- Used outside this class to remove individual elite mobs
- */
- public static void unregisterEliteMob(EliteMobEntity eliteMobEntity) {
- eliteMobs.remove(eliteMobEntity);
- naturalEntities.remove(eliteMobEntity.getLivingEntity());
- cullablePluginEntities.remove(eliteMobEntity.getLivingEntity());
- }
-
- /*
- Used in this class to do mass wipes of data
- */
- private static void unregisterEliteMob(Entity entity) {
- if (!isEliteMob(entity)) return;
- EliteMobEntity eliteMobEntity = getAsyncEliteMobEntity(entity);
- if (eliteMobEntity == null) return;
- eliteMobEntity.getLivingEntity().remove();
- eliteMobs.remove(eliteMobEntity);
- eliteMobsLivingEntities.remove(eliteMobEntity.getLivingEntity());
- }
-
- public static void unregisterArmorStand(Entity armorStand) {
- if (!armorStand.getType().equals(EntityType.ARMOR_STAND)) return;
- armorStands.remove(armorStand);
- }
-
- public static HashSet getEliteMobs() {
- return eliteMobs;
- }
-
- public static boolean getIsArmorStand(Entity entity) {
- if (!entity.getType().equals(EntityType.ARMOR_STAND)) return false;
- return (armorStands.contains(entity));
- }
-
- public static void unregisterSuperMob(Entity entity) {
- if (!SuperMobProperties.isValidSuperMobType(entity)) return;
- superMobs.remove(entity);
- }
-
- public static void unregisterNaturalEntity(Entity entity) {
- if (EliteMobProperties.isValidEliteMobType(entity)) return;
- naturalEntities.remove(entity);
- }
-
- /*
- Custom spawn reasons can be considered as natural spawns under specific config options
- */
- @EventHandler(priority = EventPriority.LOW)
- public void registerNaturalEntity(CreatureSpawnEvent event) {
- if (event.isCancelled()) return;
- if (event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.NATURAL) ||
- event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.CUSTOM) &&
- !ConfigValues.defaultConfig.getBoolean(DefaultConfig.STRICT_SPAWNING_RULES))
- registerNaturalEntity(event.getEntity());
- }
-
- /*
- Natural entities get unregistered from being natural when exploit abuse is detected from the players
- */
- public static void unregisterNaturalEntity(LivingEntity livingEntity) {
- naturalEntities.remove(livingEntity);
- }
-
- public static void shutdownPurger() {
-
- for (Entity entity : cullablePluginEntities)
- entity.remove();
-
- eliteMobs.clear();
- eliteMobsLivingEntities.clear();
- superMobs.clear();
- itemVisualEffects.clear();
- armorStands.clear();
- naturalEntities.clear();
- cullablePluginEntities.clear();
-
- }
-
- /*
- This is run in sync for performance reasons
- */
- public static void wipeEntity(Entity entity) {
- new BukkitRunnable() {
- @Override
- public void run() {
- unregisterEliteMob(entity);
- unregisterSuperMob(entity);
- unregisterNaturalEntity(entity);
- unregisterArmorStand(entity);
- unregisterCullableEntity(entity);
- }
- }.runTaskAsynchronously(MetadataHandler.PLUGIN);
- }
-
- public static void chunkWiper(ChunkUnloadEvent event) {
- for (Entity entity : event.getChunk().getEntities())
- wipeEntity(entity);
- }
-
- public static void deathWipe(EntityDeathEvent event) {
- wipeEntity(event.getEntity());
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java b/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java
index 1441924a5..55ef6107d 100644
--- a/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java
+++ b/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java
@@ -1,206 +1,405 @@
package com.magmaguy.elitemobs;
-import com.magmaguy.elitemobs.adventurersguild.AdventurersGuildGUI;
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.adventurersguild.GuildRankMenuHandler;
+import com.magmaguy.elitemobs.adventurersguild.WorldSwitchBehavior;
+import com.magmaguy.elitemobs.api.*;
import com.magmaguy.elitemobs.collateralminecraftchanges.*;
-import com.magmaguy.elitemobs.combattag.CombatTag;
-import com.magmaguy.elitemobs.commands.LootGUI;
-import com.magmaguy.elitemobs.commands.shops.CustomShopHandler;
-import com.magmaguy.elitemobs.commands.shops.ItemSaleEvent;
-import com.magmaguy.elitemobs.commands.shops.ShopHandler;
+import com.magmaguy.elitemobs.combatsystem.EliteCreeperExplosionHandler;
+import com.magmaguy.elitemobs.combatsystem.EliteMobDamagedByEliteMobHandler;
+import com.magmaguy.elitemobs.combatsystem.EliteMobGenericDamagedHandler;
+import com.magmaguy.elitemobs.combatsystem.PlayerDamagedByEliteMobHandler;
+import com.magmaguy.elitemobs.combatsystem.antiexploit.*;
+import com.magmaguy.elitemobs.combatsystem.combattag.CombatTag;
+import com.magmaguy.elitemobs.combatsystem.displays.HealthDisplay;
+import com.magmaguy.elitemobs.combatsystem.displays.PopupDisplay;
+import com.magmaguy.elitemobs.commands.admin.RemoveCommand;
+import com.magmaguy.elitemobs.commands.setup.SetupMenu;
import com.magmaguy.elitemobs.config.*;
-import com.magmaguy.elitemobs.events.DeadMoon;
-import com.magmaguy.elitemobs.events.SmallTreasureGoblin;
-import com.magmaguy.elitemobs.events.actionevents.BalrogEvent;
-import com.magmaguy.elitemobs.events.actionevents.FaeEvent;
-import com.magmaguy.elitemobs.events.actionevents.KrakenEvent;
-import com.magmaguy.elitemobs.events.mobs.*;
-import com.magmaguy.elitemobs.events.mobs.sharedeventpowers.SpiritWalk;
+import com.magmaguy.elitemobs.config.enchantments.EnchantmentsConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.events.ActionEvent;
+import com.magmaguy.elitemobs.explosionregen.Explosion;
+import com.magmaguy.elitemobs.gamemodes.nightmaremodeworld.DaylightWatchdog;
+import com.magmaguy.elitemobs.gamemodes.zoneworld.ZoneWarner;
+import com.magmaguy.elitemobs.initialsetup.FirstTimeSetup;
+import com.magmaguy.elitemobs.instanced.ArenaInstance;
+import com.magmaguy.elitemobs.instanced.MatchInstance;
import com.magmaguy.elitemobs.items.*;
-import com.magmaguy.elitemobs.items.customenchantments.FlamethrowerEnchantment;
-import com.magmaguy.elitemobs.mobconstructor.CombatSystem;
+import com.magmaguy.elitemobs.items.customenchantments.*;
+import com.magmaguy.elitemobs.items.potioneffects.PlayerPotionEffects;
+import com.magmaguy.elitemobs.menus.*;
import com.magmaguy.elitemobs.mobconstructor.MergeHandler;
-import com.magmaguy.elitemobs.mobconstructor.displays.DamageDisplay;
-import com.magmaguy.elitemobs.mobconstructor.displays.DisplayMob;
-import com.magmaguy.elitemobs.mobconstructor.displays.HealthDisplay;
-import com.magmaguy.elitemobs.mobpowers.AggroPrevention;
-import com.magmaguy.elitemobs.mobpowers.defensivepowers.InvulnerabilityArrow;
-import com.magmaguy.elitemobs.mobpowers.defensivepowers.InvulnerabilityFallDamage;
-import com.magmaguy.elitemobs.mobpowers.defensivepowers.InvulnerabilityFire;
-import com.magmaguy.elitemobs.mobpowers.defensivepowers.InvulnerabilityKnockback;
-import com.magmaguy.elitemobs.mobpowers.majorpowers.*;
-import com.magmaguy.elitemobs.mobpowers.miscellaneouspowers.BonusLoot;
-import com.magmaguy.elitemobs.mobpowers.miscellaneouspowers.Taunt;
-import com.magmaguy.elitemobs.mobpowers.offensivepowers.*;
+import com.magmaguy.elitemobs.mobconstructor.SimplePersistentEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.*;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.transitiveblocks.TransitiveBlockCommand;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.transitiveblocks.TransitiveBossBlock;
import com.magmaguy.elitemobs.mobs.passive.*;
-import com.magmaguy.elitemobs.mobspawning.NaturalEliteMobSpawnEventHandler;
import com.magmaguy.elitemobs.mobspawning.NaturalMobSpawnEventHandler;
+import com.magmaguy.elitemobs.npcs.NPCDamageEvent;
+import com.magmaguy.elitemobs.npcs.NPCInteractions;
+import com.magmaguy.elitemobs.npcs.chatter.NPCProximitySensor;
+import com.magmaguy.elitemobs.ondeathcommands.OnDeathCommands;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.playerdata.PlayerStatsTracker;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.playerdata.statusscreen.*;
+import com.magmaguy.elitemobs.powers.bosspowers.*;
+import com.magmaguy.elitemobs.powers.defensivepowers.InvulnerabilityArrow;
+import com.magmaguy.elitemobs.powers.defensivepowers.InvulnerabilityFallDamage;
+import com.magmaguy.elitemobs.powers.defensivepowers.InvulnerabilityKnockback;
+import com.magmaguy.elitemobs.powers.defensivepowers.ShieldWall;
+import com.magmaguy.elitemobs.powers.majorpowers.blaze.TrackingFireball;
+import com.magmaguy.elitemobs.powers.majorpowers.enderdragon.EnderDragonEmpoweredLightning;
+import com.magmaguy.elitemobs.powers.majorpowers.skeleton.SkeletonPillar;
+import com.magmaguy.elitemobs.powers.majorpowers.skeleton.SkeletonTrackingArrow;
+import com.magmaguy.elitemobs.powers.majorpowers.zombie.ZombieBloat;
+import com.magmaguy.elitemobs.powers.majorpowers.zombie.ZombieFriends;
+import com.magmaguy.elitemobs.powers.majorpowers.zombie.ZombieNecronomicon;
+import com.magmaguy.elitemobs.powers.majorpowers.zombie.ZombieParents;
+import com.magmaguy.elitemobs.powers.meta.Bombardment;
+import com.magmaguy.elitemobs.powers.meta.CombatEnterScanPower;
+import com.magmaguy.elitemobs.powers.meta.CustomSummonPower;
+import com.magmaguy.elitemobs.powers.miscellaneouspowers.*;
+import com.magmaguy.elitemobs.powers.offensivepowers.*;
+import com.magmaguy.elitemobs.powers.specialpowers.EnderCrystalLightningRod;
import com.magmaguy.elitemobs.powerstances.EffectEventHandlers;
import com.magmaguy.elitemobs.powerstances.VisualEffectObfuscator;
+import com.magmaguy.elitemobs.quests.CustomQuest;
+import com.magmaguy.elitemobs.quests.QuestTracking;
+import com.magmaguy.elitemobs.quests.menus.QuestInventoryMenu;
+import com.magmaguy.elitemobs.quests.objectives.CustomFetchObjective;
+import com.magmaguy.elitemobs.quests.objectives.DialogObjective;
+import com.magmaguy.elitemobs.quests.objectives.KillObjective;
+import com.magmaguy.elitemobs.quests.playercooldowns.PlayerQuestCooldownsLogout;
+import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardDungeonFlag;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardEliteMobOnlySpawnFlag;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardSpawnEventBypasser;
+import com.magmaguy.elitemobs.treasurechest.TreasureChest;
import com.magmaguy.elitemobs.utils.VersionChecker;
+import com.magmaguy.elitemobs.wormhole.WormholeEntry;
import org.bukkit.Bukkit;
+import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
public class EventsRegistrer {
+ private static PluginManager pluginManager;
+ private static Plugin plugin;
+
+ private EventsRegistrer() {
+ }
+
public static void registerEvents() {
- PluginManager pluginManager = Bukkit.getPluginManager();
- Plugin plugin = MetadataHandler.PLUGIN;
+ pluginManager = Bukkit.getPluginManager();
+ plugin = MetadataHandler.PLUGIN;
+
+ register(new FirstTimeSetup());
+
+ register(new com.magmaguy.elitemobs.versionnotifier.VersionChecker.VersionCheckerEvents());
+
+ register(new PlayerData.PlayerDataEvents());
+ register(new ElitePlayerInventory.ElitePlayerInventoryEvents());
+ register(new PlayerStatsTracker());
+ register(new PlayerQuestCooldownsLogout());
- //Load passive mobs TODO: find generic alternative to this
- pluginManager.registerEvents(new ChickenHandler(), plugin);
- pluginManager.registerEvents(new CowHandler(), plugin);
- pluginManager.registerEvents(new MushroomCowHandler(), plugin);
- pluginManager.registerEvents(new PassiveEliteMobDeathHandler(), plugin);
- pluginManager.registerEvents(new PigHandler(), plugin);
- pluginManager.registerEvents(new SheepHandler(), plugin);
- pluginManager.registerEvents(new FindSuperMobs(), plugin);
+ register(new ChickenHandler());
+ register(new CowHandler());
+ register(new MushroomCowHandler());
+ register(new PassiveEliteMobDeathHandler());
+ register(new PigHandler());
+ register(new SheepHandler());
+ register(new FindSuperMobs());
+ if (ItemSettingsConfig.isPreventEliteItemEnchantment())
+ register(new ItemEnchantmentPrevention());
+ if (!VersionChecker.serverVersionOlderThan(15, 2))
+ if (ItemSettingsConfig.isPreventEliteItemDiamondToNetheriteUpgrade())
+ register(new PreventUpgradeDiamondToNetherite());
//Mob damage
- pluginManager.registerEvents(new CombatSystem(), plugin);
- if (ConfigValues.mobCombatSettingsConfig.getBoolean(MobCombatSettingsConfig.ENABLE_DEATH_MESSAGES))
- pluginManager.registerEvents(new PlayerDeathMessageByEliteMob(), plugin);
+ register(new PlayerDamagedByEliteMobHandler());
+ register(new EliteCreeperExplosionHandler());
+ register(new EliteMobGenericDamagedHandler());
+ register(new EliteMobDamagedByEliteMobHandler());
+ if (MobCombatSettingsConfig.isEnableDeathMessages())
+ register(new PlayerDeathMessageByEliteMob());
+
+ //explosion regenerator
+ if (DefaultConfig.isDoExplosionRegen())
+ register(new Explosion.ExplosionEvent());
//Mob loot
- pluginManager.registerEvents(new DefaultDropsHandler(), plugin);
+ register(new DefaultDropsHandler());
+ register(new ItemLootShower.ItemLootShowerEvents());
+
+ //potion effects - also initializes the task
+ register(new PlayerPotionEffects());
+
+ //getloot AdventurersGuildMenu
+ register(new GetLootMenu.GetLootMenuListener());
- //potion effects
- pluginManager.registerEvents(new PotionEffectApplier(), plugin);
+ /*
+ Register API events
+ */
+ register(new EliteMobDeathEvent.EliteMobDeathEventFilter());
+ register(new EliteMobTargetPlayerEvent.EliteMobTargetPlayerEventFilter());
+ register(new EliteMobDamagedEvent.EliteMobDamageEventFilter());
+ register(new PlayerDamagedByEliteMobEvent.PlayerDamagedByEliteMobEventFilter());
+ register(new EliteMobDamagedByEliteMobEvent.EliteMobDamagedByEliteMobFilter());
+ register(new EliteMobEnterCombatEvent.EliteMobEnterCombatEventFilter());
+ register(new PlayerPreTeleportEvent.PlayerPreTeleportEventEvents());
+ register(new PlayerTeleportEvent.PlayerTeleportEventExecutor());
+ register(new SuperMobDamageEvent.SuperMobDamageEventFilter());
+ register(new EliteMobDamagedByPlayerEvent.EliteMobDamagedByPlayerEventFilter());
+ register(new EliteExplosionEvent.EliteExplosionEvents());
+
+ //Wormholes
+ register(new WormholeEntry.WormholeEntryEvent());
- //getloot AdventurersGuildGUI
- pluginManager.registerEvents(new LootGUI(), plugin);
/*
While these powers could be registered in a more automated way, I realized that it's also a bad way of getting
silent errors without ever noticing, and ultimately the amount of manual input required is pretty minimal
*/
//Minor mob powers
- pluginManager.registerEvents(new InvulnerabilityArrow(), plugin);
- pluginManager.registerEvents(new InvulnerabilityFallDamage(), plugin);
- pluginManager.registerEvents(new InvulnerabilityFire(), plugin);
- pluginManager.registerEvents(new InvulnerabilityKnockback(), plugin);
- pluginManager.registerEvents(new BonusLoot(), plugin);
- pluginManager.registerEvents(new Taunt(), plugin);
- pluginManager.registerEvents(new AttackArrow(), plugin);
- pluginManager.registerEvents(new AttackBlinding(), plugin);
- pluginManager.registerEvents(new AttackFire(), plugin);
- pluginManager.registerEvents(new AttackFireball(), plugin);
- pluginManager.registerEvents(new AttackFreeze(), plugin);
- pluginManager.registerEvents(new AttackGravity(), plugin);
- pluginManager.registerEvents(new AttackPoison(), plugin);
- pluginManager.registerEvents(new AttackPush(), plugin);
- pluginManager.registerEvents(new AttackWeakness(), plugin);
- pluginManager.registerEvents(new AttackWeb(), plugin);
- pluginManager.registerEvents(new AttackWither(), plugin);
+ register(new InvulnerabilityArrow());
+ register(new InvulnerabilityFallDamage());
+ register(new InvulnerabilityKnockback());
+ register(new BonusLoot());
+ register(new Taunt());
+ register(new Corpse());
+ register(new Implosion());
+ register(new AttackArrow());
+ register(new ArrowFireworks());
+ register(new AttackBlinding());
+ register(new AttackFire());
+ register(new AttackFireball());
+ register(new TrackingFireball.TrackingFireballEvents());
+ register(new AttackFreeze());
+ register(new AttackGravity());
+ register(new AttackLightning());
+ register(new AttackPoison());
+ register(new AttackPush());
+ register(new AttackWeakness());
+ register(new AttackWeb());
+ register(new AttackWither());
+ register(new AttackVacuum());
+ register(new ArrowRain());
+ register(new GroundPound());
+ register(new LightningBolts());
+ register(new FrostCone());
+ register(new Thunderstorm());
+ register(new Firestorm());
+ register(new Bombardment.BombardmentEvents());
+ register(new ShieldWall.ShieldWallEvents());
//Major mob powers
- pluginManager.registerEvents(new SkeletonPillar(), plugin);
- pluginManager.registerEvents(new SkeletonTrackingArrow(), plugin);
- pluginManager.registerEvents(new ZombieBloat(), plugin);
- pluginManager.registerEvents(new ZombieFriends(), plugin);
- pluginManager.registerEvents(new ZombieNecronomicon(), plugin);
- pluginManager.registerEvents(new ZombieParents(), plugin);
- pluginManager.registerEvents(new ZombieTeamRocket(), plugin);
+ register(new SkeletonPillar());
+ register(new SkeletonTrackingArrow());
+ register(new ZombieBloat());
+ register(new ZombieFriends());
+ register(new ZombieNecronomicon());
+ register(new ZombieParents());
+
+ //boss powers
+ register(new SpiritWalk());
+ register(new GoldShotgun());
+ register(new GoldExplosion());
+ register(new Flamethrower());
+ register(new PlasmaBootsEnchantment.PlasmaBootsEnchantmentEvents());
+ if (EnchantmentsConfig.getEnchantment(SoulbindEnchantment.key + ".yml").isEnabled())
+ register(new SoulbindEnchantment.SoulbindEnchantmentEvents());
+ register(new FlamePyre());
+ register(new SummonTheReturned());
+ register(new HyperLoot());
+ register(new SummonTheReturned());
+ register(new SummonEmbers());
+ register(new MeteorShower());
+ register(new BulletHell());
+ register(new DeathSlice());
+ register(new FireworksBarrage.FireworksBarrageEvents());
+ register(new CustomSummonPower.CustomSummonPowerEvent());
+ register(new EnderDragonEmpoweredLightning.EnderDragonEmpoweredLightningEvents());
+ register(new CombatEnterScanPower.MajorCombatEnterScanningPowerEvents());
+ register(new LightningEnchantment.LightningEnchantmentEvents());
+ register(new BonusCoins.BonusCoinsEvents());
+
+ //special powers
+ register(new EnderCrystalLightningRod.EnderCrystalLightningRodEvents());
+
+ //Custom bosses
+ register(new CustomBossEntity.CustomBossEntityEvents());
+ register(new CustomBossDeath());
+ register(new SimplePersistentEntity.PersistentEntityEvent());
+ register(new CustomBossTaunts());
+ register(new PhaseBossEntity.PhaseBossEntityListener());
+ register(new RegionalBossEntity.RegionalBossEntityEvents());
+ register(new AdvancedAggroManager());
+ register(new TransitiveBossBlock());
+ register(new TransitiveBlockCommand.TemporaryBossBlockCommandEvents());
+ register(new CustomModel.ModelEntityEvents());
//Metadata (player purger)
- pluginManager.registerEvents(new MetadataHandler(), plugin);
+ register(new MetadataHandler());
- //Mob merger TODO: maybe add a config scan here?
- pluginManager.registerEvents(new MergeHandler(), plugin);
+ //Mob merger
+ register(new MergeHandler());
//Natural EliteMobs Spawning
- if (ConfigValues.mobCombatSettingsConfig.getBoolean(MobCombatSettingsConfig.NATURAL_MOB_SPAWNING)) {
- pluginManager.registerEvents(new NaturalEliteMobSpawnEventHandler(), plugin);
- pluginManager.registerEvents(new EntityTracker(), plugin);
- }
+ register(new EntityTracker());
+ //Fix lingering entity after crashes
+ register(new CrashFix());
//Natural Mob Metadata Assigner
- pluginManager.registerEvents(new NaturalMobSpawnEventHandler(), plugin);
+ register(new NaturalMobSpawnEventHandler());
//Visual effects
- pluginManager.registerEvents(new EffectEventHandlers(), plugin);
- if (ConfigValues.mobCombatSettingsConfig.getBoolean(MobCombatSettingsConfig.OBFUSCATE_MOB_POWERS))
- pluginManager.registerEvents(new VisualEffectObfuscator(), plugin);
+ register(new EffectEventHandlers());
+ if (MobCombatSettingsConfig.isObfuscateMobPowers())
+ register(new VisualEffectObfuscator());
//Loot
- if (ConfigValues.itemsDropSettingsConfig.getBoolean(ItemsDropSettingsConfig.ENABLE_PLUGIN_LOOT)) {
- pluginManager.registerEvents(new LootTables(), plugin);
- pluginManager.registerEvents(new PlaceEventPrevent(), plugin);
+ if (ItemSettingsConfig.isDoEliteMobsLoot()) {
+ register(new LootTables());
+ register(new PlaceEventPrevent());
}
+ //player status menu
+ register(new CoverPage.CoverPageEvents());
+ register(new StatsPage.StatsPageEvents());
+ register(new GearPage.GearPageEvents());
+ register(new TeleportsPage.TeleportsPageEvents());
+ register(new CommandsPage.CommandsPageEvents());
+ register(new BossTrackingPage.BossTrackingPageEvents());
+
//Shops
- pluginManager.registerEvents(new ShopHandler(), plugin);
- pluginManager.registerEvents(new CustomShopHandler(), plugin);
- pluginManager.registerEvents(new ItemSaleEvent(), plugin);
+ register(new ProceduralShopMenu());
+ register(new CustomShopMenu());
+ register(new BuyOrSellMenu());
+ register(new SellMenu());
+ register(new SetupMenu.SetupMenuListeners());
+ register(new ScrapperMenu.ScrapperMenuEvents());
+ register(new SmeltMenu.SmeltMenuEvents());
+ register(new RepairMenu.RepairMenuEvents());
+ register(new RefinerMenu.RefinerMenuEvents());
+ register(new EnhancementMenu.EnhancementMenuEvents());
+ register(new UnbindMenu.UnbinderMenuEvents());
//Minecraft behavior canceller
- pluginManager.registerEvents(new ChunkUnloadMetadataPurge(), plugin);
- pluginManager.registerEvents(new EntityDeathDataFlusher(), plugin);
- if (ConfigValues.defaultConfig.getBoolean(DefaultConfig.CREEPER_PASSIVE_DAMAGE_PREVENTER))
- pluginManager.registerEvents(new PreventCreeperPassiveEntityDamage(), plugin);
- //Prevent exploits
- //Prevent mount exploit
- if (ConfigValues.defaultConfig.getBoolean(DefaultConfig.PREVENT_MOUNT_EXPLOIT))
- pluginManager.registerEvents(new PreventMountExploit(), plugin);
- //Prevent darkroom exploit
- if (ConfigValues.defaultConfig.getBoolean(DefaultConfig.PREVENT_DARKROOM_EXPLOIT))
- pluginManager.registerEvents(new PreventDarkroomExploit(), plugin);
- //Prevent tower exploit
- if (ConfigValues.defaultConfig.getBoolean(DefaultConfig.PREVENT_TOWER_EXPLOIT))
- pluginManager.registerEvents(new PreventTowerExploit(), plugin);
-
-
- if (!VersionChecker.currentVersionIsUnder(11, 0)) {
- //Initialize custom events
- pluginManager.registerEvents(new SmallTreasureGoblin(), plugin);
- pluginManager.registerEvents(new TreasureGoblin(), plugin);
- pluginManager.registerEvents(new DeadMoon(), plugin);
- pluginManager.registerEvents(new TheReturned(), plugin);
- pluginManager.registerEvents(new ZombieKing(), plugin);
- pluginManager.registerEvents(new SpiritWalk(), plugin);
-
- if (ConfigValues.eventsConfig.getBoolean(EventsConfig.KRAKEN_ENABLED)) {
- pluginManager.registerEvents(new Kraken(), plugin);
- pluginManager.registerEvents(new KrakenEvent(), plugin);
- }
- if (ConfigValues.eventsConfig.getBoolean(EventsConfig.BALROG_ENABLED)) {
- pluginManager.registerEvents(new Balrog(), plugin);
- pluginManager.registerEvents(new BalrogEvent(), plugin);
- }
- if (ConfigValues.eventsConfig.getBoolean(EventsConfig.FAE_ENABLED)) {
- pluginManager.registerEvents(new FaeEvent(), plugin);
- pluginManager.registerEvents(new Fae(), plugin);
- }
+ if (DefaultConfig.isPreventCreeperDamageToPassiveMobs())
+ register(new PreventCreeperPassiveEntityDamage());
+ if (!VersionChecker.serverVersionOlderThan(16, 0))
+ register(new PreventEliteBeeHiveEnter());
+ register(new EnderDragonUnstuck());
+ if (DefaultConfig.isPreventVanillaReinforcementsForEliteEntities())
+ register(new VanillaReinforcementsCanceller());
+ register(new LightningSpawnBypass());
+ if (ItemSettingsConfig.isEliteDurability())
+ register(new AlternativeDurabilityLoss());
+ register(new EnderCrystalDamageProtectionBypass());
+
+
+ //Antiexploits
+ register(new PreventMountExploit());
+ register(new PreventDarkroomExploit());
+ register(new PreventLargeDarkroomExploit());
+ register(new PreventTowerExploit());
+ register(new PreventEndermanHeightExploit());
+ if (AntiExploitConfig.isNoItemPickup())
+ register(new PreventItemPickupByMobs());
+ if (AntiExploitConfig.isAmbientDamageExploit())
+ register(new AmbientDamageExploit());
+ if (!VersionChecker.serverVersionOlderThan(14, 0)) {
+ register(new HoneyBlockJumpExploit());
}
+ register(new EliteMobDamagedByPlayerAntiExploitListener());
+ register(new ActionEvent.ActionEventEvents());
//Set up health and damage displays
- if (ConfigValues.mobCombatSettingsConfig.getBoolean(MobCombatSettingsConfig.DISPLAY_HEALTH_ON_HIT))
- pluginManager.registerEvents(new HealthDisplay(), plugin);
- if (ConfigValues.mobCombatSettingsConfig.getBoolean(MobCombatSettingsConfig.DISPLAY_DAMAGE_ON_HIT))
- pluginManager.registerEvents(new DamageDisplay(), plugin);
+ if (MobCombatSettingsConfig.isDisplayHealthOnHit())
+ register(new HealthDisplay());
+ if (MobCombatSettingsConfig.isDisplayDamageOnHit())
+ register(new PopupDisplay());
//Initialize items from custom events
- pluginManager.registerEvents(new FlamethrowerEnchantment(), plugin);
+ register(new FlamethrowerEnchantment.FlamethrowerEnchantmentEvents());
+ register(new SummonMerchantEnchantment.SummonMerchantEvents());
+ register(new SummonWolfEnchantment.SummonWolfEnchantmentEvent());
+ register(new MeteorShowerEnchantment.MeteorShowerEvents());
+ register(new DrillingEnchantment.DrillingEnchantmentEvents());
+ register(new IceBreakerEnchantment.IceBreakerEnchantmentEvent());
+ register(new GrapplingHookEnchantment.GrapplingHookEnchantmentEvents());
+ register(new EarthquakeEnchantment.EarthquakeEnchantmentEvents());
+ //register(new UnbindEnchantment.UnbindEvents());
//Initialize adventurer's guild
- pluginManager.registerEvents(new AdventurersGuildGUI(), plugin);
+ register(new GuildRankMenuHandler());
+ register(new WorldSwitchBehavior());
+ //register quests
+ register(new KillObjective.KillObjectiveEvents());
+ register(new CustomFetchObjective.CustomFetchObjectiveEvents());
+ register(new DialogObjective.DialogObjectiveEvents());
+ register(new QuestAcceptEvent.QuestAcceptEventHandler());
+ register(new QuestCompleteEvent.QuestCompleteEventHandler());
+ register(new QuestLeaveEvent.QuestLeaveEventHandler());
+ register(new QuestProgressionEvent.QuestProgressionEventHandler());
+ register(new QuestTracking.QuestTrackingEvents());
+ register(new CustomQuest.CustomQuestEvents());
+ register(new QuestInventoryMenu.QuestInventoryMenuEvents());
+
+ //Arenas
+ register(new ArenaMenu.ArenaMenuEvents());
+ register(new ArenaInstance.ArenaInstanceEvents());
+ register(new MatchInstance.MatchInstanceEvents());
//Combat tag
- if (ConfigValues.combatTagConfig.getBoolean(CombatTagConfig.ENABLE_COMBAT_TAG))
- pluginManager.registerEvents(new CombatTag(), plugin);
+ if (CombatTagConfig.isEnableCombatTag())
+ register(new CombatTag());
- //Prevent elitemob on elitemob aggro
- pluginManager.registerEvents(new AggroPrevention(), plugin);
- //Refresh display case Elite Mobs
- pluginManager.registerEvents(new DisplayMob(), plugin);
+ //Prevent elitemob on elitemob aggro
+ register(new EnderDragonUnstuck.AggroPrevention());
//Player effect when a rare item is on the ground
- if (ConfigValues.itemsDropSettingsConfig.getBoolean(ItemsDropSettingsConfig.ENABLE_RARE_DROP_EFFECT))
- pluginManager.registerEvents(new RareDropEffect(), plugin);
+ register(new RareDropEffect());
+
+ //NPCs
+ register(new NPCDamageEvent());
+ register(new NPCInteractions());
+ register(new NPCProximitySensor());
+ register(new FindNewWorlds());
+ register(new WorldGuardSpawnEventBypasser());
+ register(new WorldGuardEliteMobOnlySpawnFlag());
+ register(new WorldGuardDungeonFlag());
+
+ register(new EntityTransformHandler());
+ register(new EliteBlazeWaterDamagePrevention());
+ register(new PreventEliteEquipmentDrop());
+ register(new CombustionPrevention());
+
+ register(new TreasureChest.TreasureChestEvents());
+
+ //Zone based spawning
+ register(new ZoneWarner());
+ register(new DaylightWatchdog());
+
+ //On death commands
+ register(new OnDeathCommands());
+
+ //Player stuff
+ register(new GuildRank.GuildRankEvents());
+
+ //Commands
+ register(new RemoveCommand.RemoveCommandEvents());
+
+ }
+ private static void register(Listener listener) {
+ pluginManager.registerEvents(listener, plugin);
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/MetadataHandler.java b/src/main/java/com/magmaguy/elitemobs/MetadataHandler.java
index c6ca774fa..1030bfde6 100644
--- a/src/main/java/com/magmaguy/elitemobs/MetadataHandler.java
+++ b/src/main/java/com/magmaguy/elitemobs/MetadataHandler.java
@@ -1,18 +1,3 @@
-/*
- * 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 com.magmaguy.elitemobs;
import org.bukkit.Bukkit;
@@ -32,13 +17,10 @@ public class MetadataHandler implements Listener {
//plugin name
public final static String ELITE_MOBS = "EliteMobs";
-
- //plugin getter
- public final static Plugin PLUGIN = Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS);
-
//third party compatibility
public final static String BETTERDROPS_COMPATIBILITY_MD = "betterdrops_ignore";
- public final static String VANISH_NO_PACKET = "vanished";
+ //plugin getter
+ public static Plugin PLUGIN = Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS);
}
diff --git a/src/main/java/com/magmaguy/elitemobs/adventurersguild/AdventurersGuildGUI.java b/src/main/java/com/magmaguy/elitemobs/adventurersguild/AdventurersGuildGUI.java
deleted file mode 100644
index d0c65720c..000000000
--- a/src/main/java/com/magmaguy/elitemobs/adventurersguild/AdventurersGuildGUI.java
+++ /dev/null
@@ -1,382 +0,0 @@
-package com.magmaguy.elitemobs.adventurersguild;
-
-import com.magmaguy.elitemobs.ChatColorConverter;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.EconomySettingsConfig;
-import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.playerdata.PlayerData;
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemFlag;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-import org.bukkit.inventory.meta.SkullMeta;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class AdventurersGuildGUI implements Listener {
-
- private static ItemStack difficulty = new ItemStack(Material.DIAMOND_SWORD);
- private static ItemStack quest = skullItemInitializer("MHF_Question", "Quests", Arrays.asList("Coming soon!"));
-
- public static void mainMenu(Player player) {
-
- Inventory mainMenu = Bukkit.createInventory(player, 27, "Adventurer's guild");
-
- difficulty = new ItemStack(Material.DIAMOND_SWORD);
- ItemMeta difficultyMeta = difficulty.getItemMeta();
- difficultyMeta.setDisplayName("Difficulty");
- difficultyMeta.setLore(Arrays.asList("Press me to select a difficulty!"));
- difficultyMeta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
- difficulty.setItemMeta(difficultyMeta);
-
- quest = skullItemInitializer("MHF_Question", "Quests", Arrays.asList("Coming soon!"));
-
- mainMenu.setItem(11, difficulty);
- mainMenu.setItem(15, quest);
-
- player.openInventory(mainMenu);
-
- }
-
- public static void difficultyMenu(Player player) {
-
- Inventory difficultyMenu = Bukkit.createInventory(player, 27, "Guild rank selector");
-
- if (!PlayerData.playerMaxGuildRank.containsKey(player.getUniqueId())) {
- PlayerData.playerMaxGuildRank.put(player.getUniqueId(), 10);
- PlayerData.playerMaxGuildRankChanged = true;
- }
-
- if (!PlayerData.playerSelectedGuildRank.containsKey(player.getUniqueId())) {
- PlayerData.playerSelectedGuildRank.put(player.getUniqueId(), 10);
- PlayerData.playerSelectedGuildRankChanged = true;
- }
-
- for (int i = 1; i < 21; i++) {
-
- ItemStack itemStack = null;
-
- if (i <= PlayerData.playerMaxGuildRank.get(player.getUniqueId()))
- itemStack = difficultyItemStackConstructor(guildRankStatus.UNLOCKED, i, player);
- if (i > PlayerData.playerMaxGuildRank.get(player.getUniqueId()))
- itemStack = difficultyItemStackConstructor(guildRankStatus.LOCKED, i, player);
- if (i == PlayerData.playerSelectedGuildRank.get(player.getUniqueId()))
- itemStack = difficultyItemStackConstructor(guildRankStatus.SELECTED, i, player);
- if (i == PlayerData.playerMaxGuildRank.get(player.getUniqueId()) + 1) {
- itemStack = difficultyItemStackConstructor(guildRankStatus.NEXT_UNLOCK, i, player);
-
- }
-
- difficultyMenu.addItem(itemStack);
-
- }
-
- player.openInventory(difficultyMenu);
-
- }
-
- private static ItemStack difficultyItemStackConstructor(guildRankStatus guildRankStatus, int rank, Player player) {
-
- ItemStack itemStack = null;
-
- switch (guildRankStatus) {
-
- case UNLOCKED:
- itemStack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (byte) 7);
- ItemMeta unlockedMeta = itemStack.getItemMeta();
- String lowTierWarning = "";
- if (rank < 10) lowTierWarning = ChatColorConverter.convert("&cElites can't drop better loot!");
- else lowTierWarning = ChatColorConverter.convert("&aElites can drop better loot!");
- unlockedMeta.setLore(Arrays.asList(
- ChatColorConverter.convert("&f&m-------------------------------"),
- ChatColorConverter.convert( "&aThis rank is unlocked!"),
- ChatColorConverter.convert("&fYou can select it."),
- lowTierWarning,
- ChatColorConverter.convert("&f&m-------------------------------"),
- lootBonus(rank),
- mobSpawning(rank),
- difficultyBonus(rank)));
- itemStack.setItemMeta(unlockedMeta);
- break;
- case LOCKED:
- itemStack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (byte) 14);
- ItemMeta lockedMeta = itemStack.getItemMeta();
- lockedMeta.setLore(Arrays.asList(
- ChatColorConverter.convert("&f&m-------------------------------"),
- ChatColorConverter.convert("&cThis rank is locked!"),
- ChatColorConverter.convert("&cYou need rank " + (PlayerData.playerMaxGuildRank.get(player.getUniqueId()) + 1) + " first!"),
- ChatColorConverter.convert("&f&m-------------------------------"),
- lootBonus(rank),
- mobSpawning(rank),
- difficultyBonus(rank)));
- itemStack.setItemMeta(lockedMeta);
- break;
- case SELECTED:
- itemStack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (byte) 5);
- ItemMeta selectedMeta = itemStack.getItemMeta();
- String tierWarning = "";
- if (rank < 10) tierWarning = ChatColorConverter.convert("&cElites can't drop better loot!");
- else tierWarning = ChatColorConverter.convert("&aElites can drop better loot!");
- selectedMeta.setLore(Arrays.asList(
- ChatColorConverter.convert("&f&m-------------------------------"),
- ChatColorConverter.convert("&aThis is your current rank!"),
- tierWarning,
- ChatColorConverter.convert("&f&m-------------------------------"),
- lootBonus(rank),
- mobSpawning(rank),
- difficultyBonus(rank)));
- itemStack.setItemMeta(selectedMeta);
- PlayerData.playerSelectedGuildRankChanged = true;
- break;
- case NEXT_UNLOCK:
- itemStack = new ItemStack(Material.STAINED_GLASS_PANE, 1, (byte) 1);
- ItemMeta nextMeta = itemStack.getItemMeta();
- String priceString = "";
- if (!PlayerData.playerCurrency.containsKey(player.getUniqueId())) PlayerData.playerCurrency.put(player.getUniqueId(), 0.0);
- if (tierPriceCalculator(rank) > PlayerData.playerCurrency.get(player.getUniqueId()))
- priceString = "&c" + tierPriceCalculator(rank);
- else
- priceString = "&a" + tierPriceCalculator(rank);
- nextMeta.setLore(Arrays.asList(
- ChatColorConverter.convert("&f&m-------------------------------"),
- ChatColorConverter.convert("&6This is the next rank you can unlock"),
- ChatColorConverter.convert("&aSelect it when you're ready!"),
- ChatColorConverter.convert("&6Costs " + priceString + " &6" + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME)),
- ChatColorConverter.convert("&fYou have &a" + PlayerData.playerCurrency.get(player.getUniqueId()) + " &f" + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME)),
- ChatColorConverter.convert("&f&m-------------------------------"),
- lootBonus(rank),
- mobSpawning(rank),
- difficultyBonus(rank)));
- itemStack.setItemMeta(nextMeta);
- PlayerData.playerMaxGuildRankChanged = true;
- break;
- }
-
- ItemMeta itemMeta = itemStack.getItemMeta();
- itemMeta.setDisplayName(rankNamer(rank) + " rank");
- itemStack.setItemMeta(itemMeta);
-
- return itemStack;
-
- }
-
- private static String rankNamer(int rank) {
-
- String name = "";
-
- if (rank == 1) name = "&8Peaceful Villager";
- if (rank == 2) name = "&8Commoner";
- if (rank == 3) name = "&8Farmer";
- if (rank == 4) name = "&8Bard";
- if (rank == 5) name = "&8Barkeep";
- if (rank == 6) name = "&8Blacksmith";
- if (rank == 7) name = "&8Merchant";
- if (rank == 8) name = "&8Wanderer";
- if (rank == 9) name = "&8Ranger";
- if (rank == 10) name = "&fCasual Adventurer";
- if (rank == 11) name = "&fAdventurer";
- if (rank == 12) name = "&fProfessional Adventurer";
- if (rank == 13) name = "&2Elite Adventurer";
- if (rank == 14) name = "&2Master Adventurer";
- if (rank == 15) name = "&2Raider";
- if (rank == 16) name = "&1Slayer";
- if (rank == 17) name = "&1Exterminator";
- if (rank == 18) name = "&5&lElite HunterEnchantment";
- if (rank == 19) name = "&5Hero";
- if (rank == 20) name = "&6&l&oLegend";
-
- return ChatColorConverter.convert(name);
-
- }
-
- private static String mobSpawning(int rank) {
-
- int mobSpawning = 0;
-
- if (rank == 1) mobSpawning = 10;
- if (rank == 2) mobSpawning = 20;
- if (rank == 3) mobSpawning = 30;
- if (rank == 4) mobSpawning = 40;
- if (rank == 5) mobSpawning = 50;
- if (rank == 6) mobSpawning = 60;
- if (rank == 7) mobSpawning = 70;
- if (rank == 8) mobSpawning = 80;
- if (rank == 9) mobSpawning = 90;
- if (rank == 10) mobSpawning = 100;
- if (rank == 11) mobSpawning = 120;
- if (rank == 12) mobSpawning = 140;
- if (rank == 13) mobSpawning = 160;
- if (rank == 14) mobSpawning = 180;
- if (rank == 15) mobSpawning = 200;
- if (rank == 16) mobSpawning = 220;
- if (rank == 17) mobSpawning = 240;
- if (rank == 18) mobSpawning = 260;
- if (rank == 19) mobSpawning = 280;
- if (rank == 20) mobSpawning = 300;
-
- return ChatColorConverter.convert("&fElite Mob spawn rate modifier: &c" + mobSpawning + "%");
-
- }
-
- private static String lootBonus(int rank) {
-
- int lootBonus = 0;
-
- if (rank == 1) lootBonus = 10;
- if (rank == 2) lootBonus = 20;
- if (rank == 3) lootBonus = 30;
- if (rank == 4) lootBonus = 40;
- if (rank == 5) lootBonus = 50;
- if (rank == 6) lootBonus = 60;
- if (rank == 7) lootBonus = 70;
- if (rank == 8) lootBonus = 80;
- if (rank == 9) lootBonus = 90;
- if (rank == 10) lootBonus = 100;
- if (rank == 11) lootBonus = 120;
- if (rank == 12) lootBonus = 140;
- if (rank == 13) lootBonus = 160;
- if (rank == 14) lootBonus = 180;
- if (rank == 15) lootBonus = 200;
- if (rank == 16) lootBonus = 220;
- if (rank == 17) lootBonus = 240;
- if (rank == 18) lootBonus = 260;
- if (rank == 19) lootBonus = 280;
- if (rank == 20) lootBonus = 300;
-
- return ChatColorConverter.convert("&fElite Mob loot modifier: &a" + lootBonus + "%");
-
- }
-
- private static String difficultyBonus(int rank) {
-
- int difficultyBonus = 0;
-
- if (rank == 1) difficultyBonus = 10;
- if (rank == 2) difficultyBonus = 20;
- if (rank == 3) difficultyBonus = 30;
- if (rank == 4) difficultyBonus = 40;
- if (rank == 5) difficultyBonus = 50;
- if (rank == 6) difficultyBonus = 60;
- if (rank == 7) difficultyBonus = 70;
- if (rank == 8) difficultyBonus = 80;
- if (rank == 9) difficultyBonus = 90;
- if (rank == 10) difficultyBonus = 100;
- if (rank == 11) difficultyBonus = 110;
- if (rank == 12) difficultyBonus = 120;
- if (rank == 13) difficultyBonus = 130;
- if (rank == 14) difficultyBonus = 140;
- if (rank == 15) difficultyBonus = 150;
- if (rank == 16) difficultyBonus = 160;
- if (rank == 17) difficultyBonus = 170;
- if (rank == 18) difficultyBonus = 180;
- if (rank == 19) difficultyBonus = 190;
- if (rank == 20) difficultyBonus = 200;
-
- return ChatColorConverter.convert("&fElite Mob difficulty modifier: &4" + difficultyBonus + "%");
-
- }
-
- private enum guildRankStatus {
- UNLOCKED,
- SELECTED,
- NEXT_UNLOCK,
- LOCKED
- }
-
- private static void questMenu(Player player) {
-
- player.closeInventory();
- player.sendMessage("Coming soon!");
-
- }
-
- private static ItemStack skullItemInitializer(String mhfValue, String title, List lore) {
-
- ItemStack item = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- ItemMeta itemMeta = item.getItemMeta();
- SkullMeta skullMeta = (SkullMeta) itemMeta;
- skullMeta.setOwner(mhfValue);
- item.setItemMeta(skullMeta);
- itemMeta.setDisplayName(title);
- itemMeta.setLore(lore);
- item.setItemMeta(itemMeta);
-
- return item;
-
- }
-
- private static int tierPriceCalculator(int tier) {
-
- return (tier - 10) * (tier - 10) * 1000;
-
- }
-
- @EventHandler
- public void onMainMenuClick(InventoryClickEvent event) {
-
- if (!(event.getWhoClicked() instanceof Player)) return;
- if (!event.getInventory().getName().equalsIgnoreCase("Adventurer's guild")) return;
- if (event.getCurrentItem() == null || event.getCurrentItem().getType().equals(Material.AIR)) return;
- if (event.getCurrentItem().equals(difficulty))
- difficultyMenu((Player) event.getWhoClicked());
- if (event.getCurrentItem().equals(quest)) {
- event.getWhoClicked().closeInventory();
- event.getWhoClicked().sendMessage("Coming soon!");
- }
-
- event.setCancelled(true);
-
- }
-
- @EventHandler
- public void onRankSelectorClick(InventoryClickEvent event) {
-
- if (!(event.getWhoClicked() instanceof Player)) return;
- if (!event.getInventory().getName().equalsIgnoreCase("Guild rank selector")) return;
- if (event.getCurrentItem() == null || event.getCurrentItem().getType().equals(Material.AIR)) return;
-
- event.setCancelled(true);
-
- if (!event.getClickedInventory().getName().equals("Guild rank selector")){
- event.setCancelled(true);
- return;
- }
-
- int maxTier = PlayerData.playerMaxGuildRank.get(event.getWhoClicked().getUniqueId());
- int selectedTier = event.getSlot() + 1;
-
- if (selectedTier < maxTier + 1) {
- PlayerData.playerSelectedGuildRank.put(event.getWhoClicked().getUniqueId(), selectedTier);
- difficultyMenu((Player) event.getWhoClicked());
- }
-
- if (selectedTier == maxTier + 1) {
- if (EconomyHandler.checkCurrency(event.getWhoClicked().getUniqueId()) < tierPriceCalculator(selectedTier))
- event.getWhoClicked().sendMessage("[EliteMobs] You don't have enough Elite Coins! Sell some Elite Mob loot to [/em shop]!");
- else {
- EconomyHandler.subtractCurrency(event.getWhoClicked().getUniqueId(), tierPriceCalculator(selectedTier));
- PlayerData.playerMaxGuildRank.put(event.getWhoClicked().getUniqueId(), selectedTier);
- event.getWhoClicked().sendMessage(ChatColorConverter.convert("&aYou have unlocked the " + rankNamer(selectedTier) + " &arank for " +
- tierPriceCalculator(selectedTier) + " " + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME) + ". \n&6Happy hunting!"));
- difficultyMenu((Player) event.getWhoClicked());
- Bukkit.broadcastMessage(ChatColorConverter.convert(
- ((Player) event.getWhoClicked()).getDisplayName() + " has reached the " + rankNamer(selectedTier) + " &fguild rank!"));
- }
- }
-
- if (selectedTier > maxTier + 1) {
- event.getWhoClicked().sendMessage("[EliteMobs] You need to unlock other ranks first!");
- }
-
-
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRank.java b/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRank.java
index c477230b3..ee129bc38 100644
--- a/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRank.java
+++ b/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRank.java
@@ -1,20 +1,248 @@
package com.magmaguy.elitemobs.adventurersguild;
-import com.magmaguy.elitemobs.playerdata.PlayerData;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.utils.Round;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.scheduler.BukkitRunnable;
import java.util.UUID;
public class GuildRank {
- public static int getGuildRank (UUID uuid) {
+ private GuildRank() {
+ }
+
+ public static void setGuildPrestigeRank(Player player, int prestigeRank) {
+ PlayerData.setGuildPrestigeLevel(player.getUniqueId(), prestigeRank);
+ ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getFullPlayerTier(true);
+ }
+
+ public static int getGuildPrestigeRank(Player player) {
+ return getGuildPrestigeRank(player.getUniqueId());
+ }
+
+ public static int getGuildPrestigeRank(UUID player) {
+ return PlayerData.getGuildPrestigeLevel(player);
+ }
+
+ public static int getGuildPrestigeRank(Player player, boolean databaseAccess) {
+ return PlayerData.getGuildPrestigeLevel(player.getUniqueId(), databaseAccess);
+ }
- if (PlayerData.playerSelectedGuildRank.containsKey(uuid))
- return PlayerData.playerSelectedGuildRank.get(uuid);
+ public static void setMaxGuildRank(Player player, int maxGuildRank) {
+ PlayerData.setMaxGuildLevel(player.getUniqueId(), maxGuildRank);
+ }
+
+ public static int getMaxGuildRank(Player player) {
+ return PlayerData.getMaxGuildLevel(player.getUniqueId());
+ }
- PlayerData.playerSelectedGuildRank.put(uuid, 10);
+ public static int getMaxGuildRank(Player player, boolean databaseAccess) {
+ return PlayerData.getMaxGuildLevel(player.getUniqueId(), databaseAccess);
+ }
+
+ public static void setActiveGuildRank(Player player, int activeGuildRank) {
+ PlayerData.setActiveGuildLevel(player.getUniqueId(), activeGuildRank);
+ setMaxHealth(player, activeGuildRank, getGuildPrestigeRank(player));
+ }
+
+ public static int getActiveGuildRank(Player player) {
+ return PlayerData.getActiveGuildLevel(player.getUniqueId());
+ }
+
+ public static int getActiveGuildRank(Player player, boolean databaseAccess) {
+ return PlayerData.getActiveGuildLevel(player.getUniqueId(), databaseAccess);
+ }
+
+ /**
+ * Returns whether the player's maximum guild rank is below or equal to the rank to be compared.
+ *
+ * @param player Player whose maximum rank will be checked
+ * @param maxGuildLevel Target guild rank
+ * @return Whether the player's guild rank is below or equal to the target
+ */
+ public static boolean isWithinMaxGuildRank(Player player, int prestigeLevel, int maxGuildLevel) {
+ return getGuildPrestigeRank(player) >= prestigeLevel &&
+ getMaxGuildRank(player) >= maxGuildLevel;
+ }
+
+ public static boolean isWithinMaxGuildRankIgnorePrestige(Player player, int maxGuildLevel) {
+ return getMaxGuildRank(player) >= maxGuildLevel;
+ }
- return PlayerData.playerSelectedGuildRank.get(uuid);
+ /**
+ * Checks if the player's active guild rank is below or equal to the target rank.
+ *
+ * @param player Player whose active guild rank will be checked
+ * @param activeGuildLevel Target rank to check
+ * @return Whether the target rank is equal to or higher than the player's active guild rank
+ */
+ public static boolean isWithinActiveGuildRank(Player player, int prestigeLevel, int activeGuildLevel) {
+ return getGuildPrestigeRank(player) >= prestigeLevel &&
+ getActiveGuildRank(player) >= activeGuildLevel;
+ }
+
+ public static boolean isWithinActiveGuildRankIgnorePrestige(Player player, int activeGuildLevel) {
+ return getActiveGuildRank(player) >= activeGuildLevel;
+ }
+
+ /**
+ * Returns the name of the rank as set by the configuration
+ *
+ * @return Name of the rank
+ */
+ public static String getRankName(int prestige, int rank) {
+ return AdventurersGuildConfig.getRankName(prestige, rank);
+ }
+
+ public static void setMaxHealth(Player player, int activeGuildRank, int prestigeRank) {
+ if (!AdventurersGuildConfig.isAddMaxHealth()) return;
+ double guildRankBonus = healthBonusValue(prestigeRank, activeGuildRank);
+ double newMaxHealth = 20 + guildRankBonus;
+ player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(newMaxHealth);
+ }
+
+ public static void setMaxHealth(Player player) {
+ setMaxHealth(player, PlayerData.getActiveGuildLevel(player.getUniqueId()), PlayerData.getGuildPrestigeLevel(player.getUniqueId()));
+ }
+
+ public static double lootTierValue(int activeGuildRank) {
+ return activeGuildRank * 10;
+ }
+
+ public static double currencyBonusMultiplier(int prestigeLevel) {
+ return 1D + prestigeLevel * 5;
+ }
+
+ public static double currencyBonusMultiplier(UUID player) {
+ return currencyBonusMultiplier(getGuildPrestigeRank(player));
+ }
+
+ /**
+ * Returns the per-tier max health, taking prestige ranks into account
+ *
+ * @param prestigeLevel
+ * @param guildRank
+ * @return
+ */
+ public static double healthBonusValue(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddMaxHealth()) return 0;
+ double prestigeBonus = 0;
+ switch (prestigeLevel) {
+ case 0:
+ prestigeBonus = 0;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ prestigeBonus = AdventurersGuildConfig.getHealth1();
+ break;
+ case 4:
+ case 5:
+ case 6:
+ prestigeBonus = AdventurersGuildConfig.getHealth2();
+ break;
+ case 7:
+ case 8:
+ case 9:
+ prestigeBonus = AdventurersGuildConfig.getHealth3();
+ break;
+ case 10:
+ prestigeBonus = AdventurersGuildConfig.getHealth4();
+ break;
+ }
+ return prestigeBonus * guildRank;
+ }
+
+ /**
+ * Returns the per-tier dodge multiplier, taking prestige ranks into account
+ *
+ * @param prestigeLevel
+ * @param guildRank
+ * @return
+ */
+ public static double dodgeBonusValue(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddDodge()) return 0;
+ double prestigeBonus = 0;
+ switch (prestigeLevel) {
+ case 0:
+ case 1:
+ case 2:
+ prestigeBonus = 0;
+ break;
+ case 3:
+ case 4:
+ case 5:
+ prestigeBonus = AdventurersGuildConfig.getDodge1();
+ break;
+ case 6:
+ case 7:
+ case 8:
+ prestigeBonus = AdventurersGuildConfig.getDodge2();
+ break;
+ case 9:
+ case 10:
+ prestigeBonus = AdventurersGuildConfig.getDodge3();
+ break;
+ }
+ return Round.twoDecimalPlaces(guildRank / (10D + prestigeLevel) * prestigeBonus);
+ }
+
+ /**
+ * Returns the per-tier crit multiplier, taking prestige ranks into account
+ *
+ * @param prestigeLevel
+ * @param guildRank
+ * @return
+ */
+ public static double critBonusValue(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddCrit()) return 0;
+ double prestigeBonus = 0;
+ switch (prestigeLevel) {
+ case 0:
+ case 1:
+ prestigeBonus = 0;
+ break;
+ case 2:
+ case 3:
+ case 4:
+ prestigeBonus = AdventurersGuildConfig.getCrit1();
+ break;
+ case 5:
+ case 6:
+ case 7:
+ prestigeBonus = AdventurersGuildConfig.getCrit2();
+ break;
+ case 8:
+ case 9:
+ case 10:
+ prestigeBonus = AdventurersGuildConfig.getCrit3();
+ break;
+ }
+ return Round.twoDecimalPlaces(guildRank / (10D + prestigeLevel) * prestigeBonus);
+ }
+
+ public static class GuildRankEvents implements Listener {
+ @EventHandler
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ if (event.getPlayer().isOnline())
+ setMaxHealth(event.getPlayer(),
+ GuildRank.getActiveGuildRank(event.getPlayer(), true),
+ GuildRank.getGuildPrestigeRank(event.getPlayer(), true));
+ }
+ }.runTaskLater(MetadataHandler.PLUGIN, 20 * 3);
+ }
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRankMenuHandler.java b/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRankMenuHandler.java
new file mode 100644
index 000000000..5ed9459e1
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/adventurersguild/GuildRankMenuHandler.java
@@ -0,0 +1,350 @@
+package com.magmaguy.elitemobs.adventurersguild;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import com.magmaguy.elitemobs.config.EconomySettingsConfig;
+import com.magmaguy.elitemobs.config.menus.premade.GuildRankMenuConfig;
+import com.magmaguy.elitemobs.economy.EconomyHandler;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class GuildRankMenuHandler implements Listener {
+
+ private static final HashSet inventories = new HashSet<>();
+ private static final ArrayList rankSlots = new ArrayList<>(Arrays.asList(
+ 4, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42));
+ private static final int prestigeRankSlot = 49;
+
+ private static void selectUnlockedRank(Player player, int guildRank) {
+ GuildRank.setActiveGuildRank(player, guildRank);
+ }
+
+ private static void selectRankToUnlock(Player player, int guildRank) {
+ double price = tierPriceCalculator(guildRank, GuildRank.getGuildPrestigeRank(player));
+ if (EconomyHandler.checkCurrency(player.getUniqueId()) < price) {
+ player.sendMessage(GuildRankMenuConfig.getNotEnoughCurrencyMessage()
+ .replace("$neededAmount", tierPriceCalculator(guildRank, GuildRank.getGuildPrestigeRank(player)) + "")
+ .replace("$currentAmount", EconomyHandler.checkCurrency(player.getUniqueId()) + "")
+ .replace("$currencyName", EconomySettingsConfig.getCurrencyName()));
+ return;
+ }
+ EconomyHandler.subtractCurrency(player.getUniqueId(), price);
+ GuildRank.setActiveGuildRank(player, guildRank);
+ GuildRank.setMaxGuildRank(player, guildRank);
+ player.sendMessage(GuildRankMenuConfig.getUnlockMessage()
+ .replace("$rankName", GuildRank.getRankName(GuildRank.getGuildPrestigeRank(player), guildRank))
+ .replace("$price", tierPriceCalculator(guildRank, GuildRank.getGuildPrestigeRank(player)) + "")
+ .replace("$currencyName", EconomySettingsConfig.getCurrencyName()));
+
+ Bukkit.broadcastMessage(GuildRankMenuConfig.getBroadcastMessage()
+ .replace("$player", player.getDisplayName())
+ .replace("$rankName", GuildRank.getRankName(GuildRank.getGuildPrestigeRank(player), guildRank)));
+ if (!AdventurersGuildConfig.getOnRankUpCommand().isEmpty())
+ for (String command : AdventurersGuildConfig.getOnRankUpCommand())
+ Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
+ command.replace("$player", player.getName())
+ .replace("$prestigeRank", GuildRank.getActiveGuildRank(player) + "")
+ .replace("$activeRank", GuildRank.getGuildPrestigeRank(player) + ""));
+ }
+
+ private static void selectPrestigeUnlock(Player player) {
+ if (GuildRank.getGuildPrestigeRank(player) >= 10) return;
+ if (GuildRank.getActiveGuildRank(player) != 10 + GuildRank.getGuildPrestigeRank(player))
+ return;
+ if (EconomyHandler.checkCurrency(player.getUniqueId()) < tierPriceCalculator(GuildRank.getGuildPrestigeRank(player) + 12, GuildRank.getGuildPrestigeRank(player))) {
+ player.sendMessage(GuildRankMenuConfig.getNotEnoughCurrencyMessage()
+ .replace("$neededAmount", tierPriceCalculator(GuildRank.getGuildPrestigeRank(player) + 12, GuildRank.getGuildPrestigeRank(player)) + "")
+ .replace("$currentAmount", EconomyHandler.checkCurrency(player.getUniqueId()) + "")
+ .replace("$currencyName", EconomySettingsConfig.getCurrencyName()));
+ return;
+ }
+ EconomyHandler.setCurrency(player.getUniqueId(), 0);
+ GuildRank.setMaxGuildRank(player, 1);
+ GuildRank.setActiveGuildRank(player, 1);
+ GuildRank.setGuildPrestigeRank(player, GuildRank.getGuildPrestigeRank(player) + 1);
+
+ for (Player iteratedPlayer : Bukkit.getOnlinePlayers()) {
+ iteratedPlayer.sendTitle(
+ ChatColorConverter.convert(AdventurersGuildConfig.getPrestigeUnlockMessageSubtitle().replace("$player", player.getDisplayName())
+ .replace("$tier", GuildRank.getGuildPrestigeRank(player) + "")),
+ ChatColorConverter.convert(AdventurersGuildConfig.getPrestigeUnlockMessageSubtitle().replace("$player", player.getDisplayName())
+ .replace("$tier", GuildRank.getGuildPrestigeRank(player) + "")));
+ }
+ player.closeInventory();
+ if (!AdventurersGuildConfig.getOnPrestigeUpCommand().isEmpty())
+ for (String command : AdventurersGuildConfig.getOnPrestigeUpCommand())
+ Bukkit.dispatchCommand(Bukkit.getConsoleSender(),
+ command.replace("$player", player.getName())
+ .replace("$prestigeRank", GuildRank.getActiveGuildRank(player) + "")
+ .replace("$activeRank", GuildRank.getGuildPrestigeRank(player) + ""));
+ }
+
+ /**
+ * Using the following slots for the menu:
+ * 4 - Commoner rank
+ * Normal ranks:
+ * 11, 12, 13, 14, 15
+ * 20, 21, 22, 23, 24
+ * 39, 30, 31, 32, 34
+ * 38, 39, 40, 41, 42
+ * 49 - Prestige button
+ *
+ * @param player Player for whom the menu will be generated
+ * @return Returns the inventory generated
+ */
+ public static Inventory initializeGuildRankMenu(Player player) {
+ Inventory difficultyMenu = Bukkit.createInventory(player, 54, GuildRankMenuConfig.getMenuName());
+ difficultyMenu = populateInventory(difficultyMenu, player);
+ inventories.add(difficultyMenu);
+ player.openInventory(difficultyMenu);
+ return difficultyMenu;
+ }
+
+ public static Inventory populateInventory(Inventory difficultyMenu, Player player) {
+ for (int i = 0; i < 11 + GuildRank.getGuildPrestigeRank(player); i++) {
+ ItemStack itemStack = null;
+ if (GuildRank.isWithinActiveGuildRankIgnorePrestige(player, i)) {
+ itemStack = difficultyItemStackConstructor(guildRankStatus.UNLOCKED, i, player, false);
+ }
+ if (GuildRank.getActiveGuildRank(player) < i && GuildRank.getMaxGuildRank(player) >= i) {
+ itemStack = difficultyItemStackConstructor(guildRankStatus.UNLOCKED, i, player, false);
+ }
+ if (GuildRank.getActiveGuildRank(player) == i) {
+ itemStack = difficultyItemStackConstructor(guildRankStatus.SELECTED, i, player, false);
+ }
+ if (GuildRank.getMaxGuildRank(player) < i) {
+ itemStack = difficultyItemStackConstructor(guildRankStatus.LOCKED, i, player, false);
+ }
+ if (GuildRank.getMaxGuildRank(player) + 1 == i) {
+ itemStack = difficultyItemStackConstructor(guildRankStatus.NEXT_UNLOCK, i, player, false);
+ }
+ difficultyMenu.setItem(rankSlots.get(i), itemStack);
+ }
+
+ if (GuildRank.getGuildPrestigeRank(player) < 10) {
+ if (GuildRank.getActiveGuildRank(player) < 10 + GuildRank.getGuildPrestigeRank(player))
+ difficultyMenu.setItem(prestigeRankSlot, difficultyItemStackConstructor
+ (guildRankStatus.PRESTIGE_LOCKED, GuildRank.getGuildPrestigeRank(player) + 1, player, true));
+ else
+ difficultyMenu.setItem(prestigeRankSlot, difficultyItemStackConstructor
+ (guildRankStatus.PRESTIGE_NEXT_UNLOCK, GuildRank.getGuildPrestigeRank(player) + 1, player, true));
+ }
+
+ return difficultyMenu;
+ }
+
+ private static ItemStack difficultyItemStackConstructor(guildRankStatus guildRankStatus, int activeGuildRank, Player player, boolean isPrestigeSlot) {
+
+ ItemStack itemStack = null;
+
+ String priceString = "";
+ if (!isPrestigeSlot)
+ if (tierPriceCalculator(activeGuildRank, GuildRank.getGuildPrestigeRank(player)) > EconomyHandler.checkCurrency(player.getUniqueId()))
+ priceString = "&c" + tierPriceCalculator(activeGuildRank, GuildRank.getGuildPrestigeRank(player));
+ else
+ priceString = "&a" + tierPriceCalculator(activeGuildRank, GuildRank.getGuildPrestigeRank(player));
+ else {
+ if (tierPriceCalculator(GuildRank.getGuildPrestigeRank(player) + 12, GuildRank.getGuildPrestigeRank(player)) > EconomyHandler.checkCurrency(player.getUniqueId()))
+ priceString = "&c" + tierPriceCalculator(GuildRank.getGuildPrestigeRank(player) + 12, GuildRank.getGuildPrestigeRank(player));
+ else
+ priceString = "&a" + tierPriceCalculator(GuildRank.getGuildPrestigeRank(player) + 12, GuildRank.getGuildPrestigeRank(player));
+ }
+ switch (guildRankStatus) {
+ case UNLOCKED:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getUnlockedButton().clone(), player, priceString);
+ break;
+ case LOCKED:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getLockedButton().clone(), player, priceString);
+ break;
+ case SELECTED:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getCurrentButton().clone(), player, priceString);
+ break;
+ case NEXT_UNLOCK:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getNextButton().clone(), player, priceString);
+ break;
+ case PRESTIGE_LOCKED:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getPrestigeLockedButton().clone(), player, priceString);
+ break;
+ case PRESTIGE_NEXT_UNLOCK:
+ itemStack = constructButtonItemStack(activeGuildRank, GuildRankMenuConfig.getPrestigeNextUnlockButton().clone(), player, priceString);
+ break;
+ }
+
+ ItemMeta itemMeta = itemStack.getItemMeta();
+ if (guildRankStatus.equals(GuildRankMenuHandler.guildRankStatus.UNLOCKED) ||
+ guildRankStatus.equals(GuildRankMenuHandler.guildRankStatus.LOCKED) ||
+ guildRankStatus.equals(GuildRankMenuHandler.guildRankStatus.SELECTED) ||
+ guildRankStatus.equals(GuildRankMenuHandler.guildRankStatus.NEXT_UNLOCK))
+ itemMeta.setDisplayName(GuildRank.getRankName(GuildRank.getGuildPrestigeRank(player), activeGuildRank));
+ else
+ itemMeta.setDisplayName(itemMeta.getDisplayName().replace("$rank", GuildRank.getGuildPrestigeRank(player) + 1 + ""));
+ itemStack.setItemMeta(itemMeta);
+
+ return itemStack;
+
+ }
+
+ private static ItemStack constructButtonItemStack(int activeGuildRank, ItemStack itemStack, Player player, String priceString) {
+ ItemMeta itemMeta = itemStack.getItemMeta();
+ List newLore = new ArrayList<>();
+ for (String string : itemMeta.getLore()) {
+ switch (string) {
+ case "$lootTier":
+ if (lootTierString(activeGuildRank) != null)
+ newLore.add(lootTierString(activeGuildRank));
+ break;
+ case "$maxHealthIncrease":
+ if (healthBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank) != null)
+ newLore.add(healthBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank));
+ break;
+ case "$chanceToCrit":
+ if (critBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank) != null)
+ newLore.add(critBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank));
+ break;
+ case "$chanceToDodge":
+ if (dodgeBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank) != null)
+ newLore.add(dodgeBonusString(GuildRank.getGuildPrestigeRank(player), activeGuildRank));
+ break;
+ case "$currencyBonusMessage":
+ if (GuildRank.getGuildPrestigeRank(player) > 0)
+ newLore.add(currencyBonusString(GuildRank.getGuildPrestigeRank(player)));
+ break;
+ default:
+ if (string.contains("$previousRank")) {
+ newLore.add(string.replace("$previousRank",
+ (GuildRank.getRankName(GuildRank.getGuildPrestigeRank(player), GuildRank.getMaxGuildRank(player) + 1) + "")));
+ continue;
+ }
+ if (string.contains("$price")) {
+ newLore.add(
+ ChatColorConverter.convert(
+ string.replace("$price", priceString)
+ .replace("$currencyName", EconomySettingsConfig.getCurrencyName())));
+ continue;
+ }
+ if (string.contains("$currentCurrency")) {
+ newLore.add(string
+ .replace("$currentCurrency", EconomyHandler.checkCurrency(player.getUniqueId()) + "")
+ .replace("$currencyName", EconomySettingsConfig.getCurrencyName()));
+ continue;
+ }
+ newLore.add(string);
+ break;
+ }
+ }
+ itemMeta.setLore(newLore);
+ itemStack.setItemMeta(itemMeta);
+ return itemStack;
+ }
+
+ private static String lootTierString(int activeGuildRank) {
+ if (!AdventurersGuildConfig.isGuildLootLimiter()) return null;
+ return GuildRankMenuConfig.getLootTierMessage().replace("$tier", GuildRank.lootTierValue(activeGuildRank) + "");
+ }
+
+ private static String currencyBonusString(int activeGuildRank) {
+ return GuildRankMenuConfig.getCurrencyBonusMessage().replace("$amount", GuildRank.currencyBonusMultiplier(activeGuildRank) + "");
+ }
+
+ private static String healthBonusString(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddMaxHealth()) return null;
+ if (prestigeLevel < 1)
+ return null;
+ return GuildRankMenuConfig.getHealthBonusMessage().replace("$amount", GuildRank.healthBonusValue(prestigeLevel, guildRank) + "");
+ }
+
+ private static String critBonusString(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddMaxHealth()) return null;
+ if (prestigeLevel < 3)
+ return null;
+ return GuildRankMenuConfig.getCritBonusMessage().replace("$amount", GuildRank.critBonusValue(prestigeLevel, guildRank) + "");
+ }
+
+ private static String dodgeBonusString(int prestigeLevel, int guildRank) {
+ if (!AdventurersGuildConfig.isAddMaxHealth()) return null;
+ if (prestigeLevel < 4)
+ return null;
+ return GuildRankMenuConfig.getDodgeBonusMessage().replace("$amount", GuildRank.dodgeBonusValue(prestigeLevel, guildRank) + "");
+ }
+
+ private static int tierPriceCalculator(int tier, int prestigeLevel) {
+ /*Logic:
+ tier * 10 = max mob tier
+ max mob tier / 2 = loot shower payout for killing 1 em at max level for that player
+ payout * 1000 = amount of elite mobs to kill before going up a rank
+ */
+ double eliteMobsToKillBeforeGuildRankUp = AdventurersGuildConfig.getBaseKillsForRankUp() + AdventurersGuildConfig.getAdditionalKillsForRankUpPerTier() * (tier - 1);
+ return (int) ((tier - 1) * 10D / 2D * eliteMobsToKillBeforeGuildRankUp * (GuildRank.currencyBonusMultiplier(prestigeLevel)));
+ }
+
+ @EventHandler
+ public void onRankSelectorClick(InventoryClickEvent event) {
+ if (!(event.getWhoClicked() instanceof Player)) return;
+ if (!inventories.contains(event.getInventory())) return;
+ event.setCancelled(true);
+ Player player = (Player) event.getWhoClicked();
+
+ if (event.getSlot() == prestigeRankSlot) {
+ selectPrestigeUnlock(player);
+ return;
+ }
+ Integer selectedRank = null;
+
+ for (int i = 0; i < rankSlots.size(); i++) {
+ if (rankSlots.get(i) == event.getSlot()) {
+ selectedRank = i;
+ break;
+ }
+ }
+
+ //Clicked nothing
+ if (selectedRank == null) return;
+
+ if (GuildRank.getMaxGuildRank(player) >= selectedRank) {
+ selectUnlockedRank(player, selectedRank);
+ GuildRankMenuHandler.populateInventory(event.getInventory(), player);
+ return;
+ }
+
+ if (GuildRank.getMaxGuildRank(player) + 1 == selectedRank) {
+ selectRankToUnlock(player, selectedRank);
+ GuildRankMenuHandler.populateInventory(event.getInventory(), player);
+ return;
+ }
+
+ if (GuildRank.getMaxGuildRank(player) < selectedRank) {
+ selectPrestigeUnlock(player);
+ GuildRankMenuHandler.populateInventory(event.getInventory(), player);
+ return;
+ }
+
+ }
+
+ @EventHandler
+ public void onInventoryClose(InventoryCloseEvent event) {
+ if (!inventories.contains(event.getInventory())) return;
+ inventories.remove(event.getInventory());
+ }
+
+ private enum guildRankStatus {
+ UNLOCKED,
+ SELECTED,
+ NEXT_UNLOCK,
+ LOCKED,
+ PRESTIGE_LOCKED,
+ PRESTIGE_NEXT_UNLOCK,
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/adventurersguild/WorldSwitchBehavior.java b/src/main/java/com/magmaguy/elitemobs/adventurersguild/WorldSwitchBehavior.java
new file mode 100644
index 000000000..142b98a5e
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/adventurersguild/WorldSwitchBehavior.java
@@ -0,0 +1,22 @@
+package com.magmaguy.elitemobs.adventurersguild;
+
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerChangedWorldEvent;
+
+public class WorldSwitchBehavior implements Listener {
+ @EventHandler(ignoreCancelled = true)
+ public void onPlayerTeleport(PlayerChangedWorldEvent event) {
+ if (AdventurersGuildConfig.getWorldsWithoutAGBonuses().isEmpty()) return;
+ //to a world without bonuses
+ if (AdventurersGuildConfig.getWorldsWithoutAGBonuses().contains(event.getPlayer().getWorld().getName()) &&
+ !AdventurersGuildConfig.getWorldsWithoutAGBonuses().contains(event.getFrom().getName()))
+ event.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(event.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getDefaultValue());
+ //to a world with bonuses
+ else if (!AdventurersGuildConfig.getWorldsWithoutAGBonuses().contains(event.getPlayer().getWorld().getName()) &&
+ AdventurersGuildConfig.getWorldsWithoutAGBonuses().contains(event.getFrom().getName()))
+ GuildRank.setMaxHealth(event.getPlayer());
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/announcements/AnnouncementPriority.java b/src/main/java/com/magmaguy/elitemobs/announcements/AnnouncementPriority.java
new file mode 100644
index 000000000..f998b6b59
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/announcements/AnnouncementPriority.java
@@ -0,0 +1,23 @@
+package com.magmaguy.elitemobs.announcements;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.EventsConfig;
+import com.magmaguy.elitemobs.thirdparty.discordsrv.DiscordSRVAnnouncement;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+
+public class AnnouncementPriority {
+ private AnnouncementPriority() {
+ }
+
+ public static void announce(String message, World world, int announcementPriority) {
+ if (announcementPriority == 1 && !EventsConfig.isAnnouncementBroadcastWorldOnly())
+ Bukkit.broadcastMessage(ChatColorConverter.convert(message));
+ else
+ for (Player player : world.getPlayers())
+ player.sendMessage(ChatColorConverter.convert(message));
+ if (announcementPriority < 3) return;
+ new DiscordSRVAnnouncement(ChatColorConverter.convert(message));
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/CustomEventStartEvent.java b/src/main/java/com/magmaguy/elitemobs/api/CustomEventStartEvent.java
new file mode 100644
index 000000000..43b1bfb30
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/CustomEventStartEvent.java
@@ -0,0 +1,49 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.events.CustomEvent;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * To clear up the weird naming system here, this event is called when custom event (the type created by users for the
+ * customizable in-game event system) is called, i.e. for treasure goblins, meteors and the dead moon event.
+ */
+public class CustomEventStartEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private CustomEvent customEvent;
+ private boolean cancelled = false;
+
+ public CustomEventStartEvent(CustomEvent customEvent) {
+ this.customEvent = customEvent;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public CustomEvent getCustomEvent() {
+ return customEvent;
+ }
+
+ public void setCustomEvent(CustomEvent customEvent) {
+ this.customEvent = customEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/DamageEliteMob.java b/src/main/java/com/magmaguy/elitemobs/api/DamageEliteMob.java
new file mode 100644
index 000000000..e3542dd52
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/DamageEliteMob.java
@@ -0,0 +1,63 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.events.BossCustomAttackDamage;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.entity.Player;
+
+public class DamageEliteMob {
+
+ public static double lowDamage(EliteEntity eliteEntity) {
+ return damageFormula(eliteEntity, DamageAmount.LOW);
+ }
+
+ public static double mediumDamage(EliteEntity eliteEntity) {
+ return damageFormula(eliteEntity, DamageAmount.MEDIUM);
+ }
+
+ public static double highDamage(EliteEntity eliteEntity) {
+ return damageFormula(eliteEntity, DamageAmount.HIGH);
+ }
+
+ public static double lowDamage(Player player, EliteEntity eliteEntity) {
+ return damageFormula(player, eliteEntity, DamageAmount.LOW);
+ }
+
+ public static double mediumDamage(Player player, EliteEntity eliteEntity) {
+ return damageFormula(player, eliteEntity, DamageAmount.MEDIUM);
+ }
+
+ public static double highDamage(Player player, EliteEntity eliteEntity) {
+ return damageFormula(player, eliteEntity, DamageAmount.HIGH);
+ }
+
+ private static double damageFormula(EliteEntity eliteEntity, DamageAmount damageAmount) {
+ return eliteEntity.damage(tierCalc(eliteEntity, damageAmount));
+ }
+
+ private static double damageFormula(Player player, EliteEntity eliteEntity, DamageAmount damageAmount) {
+ return BossCustomAttackDamage.dealCustomDamage(player, eliteEntity.getLivingEntity(), tierCalc(eliteEntity, damageAmount));
+ }
+
+ public static double getDamageValue(EliteEntity eliteEntity, DamageAmount damageAmount) {
+ return tierCalc(eliteEntity, damageAmount);
+ }
+
+ private static double tierCalc(EliteEntity eliteEntity, DamageAmount damageAmount) {
+ switch (damageAmount) {
+ case LOW:
+ return Math.max(eliteEntity.getLevel() - 3, 0);
+ case MEDIUM:
+ default:
+ return eliteEntity.getLevel();
+ case HIGH:
+ return eliteEntity.getLevel() + 3;
+ }
+ }
+
+ public enum DamageAmount {
+ LOW,
+ MEDIUM,
+ HIGH
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteExplosionEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteExplosionEvent.java
new file mode 100644
index 000000000..bdac1756b
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteExplosionEvent.java
@@ -0,0 +1,153 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.CrashFix;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.powers.majorpowers.enderdragon.EnderDragonEmpoweredLightning;
+import com.magmaguy.elitemobs.powers.majorpowers.enderdragon.EnderDragonTornado;
+import com.magmaguy.elitemobs.powers.meta.ElitePower;
+import org.bukkit.Location;
+import org.bukkit.block.BlockState;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.FallingBlock;
+import org.bukkit.event.*;
+import org.bukkit.event.entity.EntityChangeBlockEvent;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.Vector;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class EliteExplosionEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ public static List fallingBlocks = new ArrayList<>();
+ private final EliteEntity eliteEntity;
+ private final List blockStates;
+ private final ElitePower elitePower;
+ private Location explosionSourceLocation;
+ private boolean isCancelled = false;
+
+ public EliteExplosionEvent(EliteEntity eliteEntity,
+ ElitePower elitePower,
+ Location explosionSourceLocation,
+ List blockStates) {
+ this.eliteEntity = eliteEntity;
+ this.explosionSourceLocation = explosionSourceLocation;
+ this.elitePower = elitePower;
+ this.blockStates = blockStates;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return eliteEntity;
+ }
+
+ public Location getExplosionSourceLocation() {
+ return explosionSourceLocation;
+ }
+
+ public void setExplosionSourceLocation(Location explosionSourceLocation) {
+ this.explosionSourceLocation = explosionSourceLocation;
+ }
+
+ public ElitePower getElitePower() {
+ return elitePower;
+ }
+
+ public List getBlockStates() {
+ return blockStates;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public void visualExplosionEffect(ElitePower elitePower) {
+ VisualExplosionEffectType visualExplosionEffectType;
+
+ if (elitePower == null)
+ visualExplosionEffectType = VisualExplosionEffectType.NORMAL;
+ else if (elitePower.getFileName().equals(new EnderDragonEmpoweredLightning().getFileName()))
+ visualExplosionEffectType = VisualExplosionEffectType.ASCEND;
+ else if (elitePower instanceof EnderDragonTornado) {
+ visualExplosionEffectType = VisualExplosionEffectType.HIGH_POWER;
+ } else
+ visualExplosionEffectType = VisualExplosionEffectType.NORMAL;
+
+ for (BlockState blockState : blockStates) {
+ FallingBlock fallingBlock = blockState.getBlock().getWorld().spawnFallingBlock(blockState.getLocation().add(new Vector(0, 0.2, 0)), blockState.getBlockData());
+ fallingBlock.setDropItem(false);
+ fallingBlock.setHurtEntities(true);
+
+ switch (visualExplosionEffectType) {
+ case ASCEND:
+ fallingBlock.setVelocity(fallingBlock.getLocation().clone().subtract(explosionSourceLocation)
+ .toVector().normalize().setY(1).normalize().multiply(ThreadLocalRandom.current().nextDouble()));
+ fallingBlock.setGravity(false);
+ fallingBlock.setGlowing(true);
+ break;
+ case HIGH_POWER:
+ fallingBlock.setVelocity(fallingBlock.getLocation().clone().subtract(explosionSourceLocation).toVector().normalize().setY(2).multiply(0.9));
+ break;
+ case NORMAL:
+ default:
+ fallingBlock.setVelocity(fallingBlock.getLocation().clone().subtract(explosionSourceLocation).toVector().normalize().setY(1).multiply(0.5));
+ }
+
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ if (fallingBlock.isValid())
+ fallingBlock.remove();
+ }
+ }.runTaskLater(MetadataHandler.PLUGIN, 20 * 4);
+
+ CrashFix.persistentTracker(fallingBlock);
+ fallingBlocks.add(fallingBlock);
+ }
+ }
+
+ public enum VisualExplosionEffectType {
+ NORMAL,
+ HIGH_POWER,
+ ASCEND
+ }
+
+ public static class EliteExplosionEvents implements Listener {
+ @EventHandler(ignoreCancelled = true)
+ public void onBlockDrop(EntityChangeBlockEvent event) {
+
+ if (fallingBlocks.isEmpty()) return;
+ if (!event.getEntity().getType().equals(EntityType.FALLING_BLOCK)) return;
+
+ boolean wasFallingBlock = false;
+ for (FallingBlock fallingBlock : fallingBlocks)
+ if (fallingBlock.equals(event.getEntity())) {
+ event.setCancelled(true);
+ wasFallingBlock = true;
+ break;
+ }
+
+ if (!wasFallingBlock) return;
+ event.getEntity().remove();
+ fallingBlocks.remove((FallingBlock) event.getEntity());
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByEliteMobEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByEliteMobEvent.java
new file mode 100644
index 000000000..1ecf73a98
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByEliteMobEvent.java
@@ -0,0 +1,84 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
+import com.magmaguy.elitemobs.utils.EntityFinder;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.*;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+
+public class EliteMobDamagedByEliteMobEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final EliteEntity damager;
+ private final EliteEntity damagee;
+ private final EntityDamageByEntityEvent entityDamageByEntityEvent;
+ private final double damage;
+ private boolean isCancelled = false;
+
+ public EliteMobDamagedByEliteMobEvent(EliteEntity damager, EliteEntity damagee, EntityDamageByEntityEvent event, double damage) {
+ this.damager = damager;
+ this.damagee = damagee;
+ this.entityDamageByEntityEvent = event;
+ this.damage = damage;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public EliteEntity getDamager() {
+ return damager;
+ }
+
+ public EliteEntity getDamagee() {
+ return damagee;
+ }
+
+ public EntityDamageByEntityEvent getEntityDamageByEntityEvent() {
+ return entityDamageByEntityEvent;
+ }
+
+ public double getDamage() {
+ return damage;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobDamagedByEliteMobFilter implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
+ public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
+ EliteEntity damagee = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (damagee == null) return;
+ LivingEntity livingEntity = EntityFinder.filterRangedDamagers(event.getDamager());
+ EliteEntity damager = EntityTracker.getEliteMobEntity(livingEntity);
+ if (damager == null) return;
+ if (damager.getLivingEntity() == null) return;
+ if (EliteMobProperties.getPluginData(damager.getLivingEntity().getType()) == null) return;
+ double damage = EliteMobProperties.getBaselineDamage(damager.getLivingEntity().getType(), damager) + damager.getLevel();
+ EliteMobDamagedByEliteMobEvent eliteMobDamagedByEliteMobEvent = new EliteMobDamagedByEliteMobEvent(damager, damagee, event, damage);
+ new EventCaller(eliteMobDamagedByEliteMobEvent);
+ if (eliteMobDamagedByEliteMobEvent.isCancelled) return;
+ event.setDamage(damage);
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerAntiExploitEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerAntiExploitEvent.java
new file mode 100644
index 000000000..eb013d635
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerAntiExploitEvent.java
@@ -0,0 +1,64 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class EliteMobDamagedByPlayerAntiExploitEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final EliteMobDamagedByPlayerEvent eliteMobDamagedByPlayerEvent;
+ private boolean isCancelled = false;
+ private boolean isTriggered = false;
+
+ public EliteMobDamagedByPlayerAntiExploitEvent(EliteEntity eliteEntity, EliteMobDamagedByPlayerEvent event) {
+ this.entity = eliteEntity.getLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.eliteMobDamagedByPlayerEvent = event;
+ if (!eliteEntity.getLivingEntity().hasAI())
+ setCancelled(true);
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return eliteEntity;
+ }
+
+ public EliteMobDamagedByPlayerEvent getEliteMobDamagedByPlayerEvent() {
+ return eliteMobDamagedByPlayerEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ public boolean isTriggered() {
+ return isTriggered;
+ }
+
+ public void setTriggered(boolean triggered) {
+ isTriggered = triggered;
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java
new file mode 100644
index 000000000..4d473e9a2
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java
@@ -0,0 +1,341 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.EliteMobs;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.combatsystem.CombatSystem;
+import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardFlagChecker;
+import com.magmaguy.elitemobs.utils.EntityFinder;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import com.magmaguy.elitemobs.utils.Round;
+import lombok.Getter;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.*;
+import org.bukkit.event.*;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashMap;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class EliteMobDamagedByPlayerEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Entity entity;
+ @Getter
+ private final EliteEntity eliteMobEntity;
+ @Getter
+ private final Player player;
+ @Getter
+ private final EntityDamageByEntityEvent entityDamageByEntityEvent;
+ @Getter
+ private final double damage;
+ @Getter
+ private final boolean criticalStrike;
+ @Getter
+ private final boolean isCustomDamage;
+ @Getter
+ private final double damageModifier;
+ @Getter
+ public boolean rangedAttack;
+ @Getter
+ private boolean isCancelled = false;
+
+ public EliteMobDamagedByPlayerEvent(EliteEntity eliteEntity,
+ Player player,
+ EntityDamageByEntityEvent event,
+ double damage,
+ boolean criticalStrike,
+ boolean isCustomDamage,
+ double damageModifier) {
+ this.damage = damage;
+ this.entity = eliteEntity.getLivingEntity();
+ this.eliteMobEntity = eliteEntity;
+ this.player = player;
+ this.entityDamageByEntityEvent = event;
+ this.rangedAttack = event.getDamager() instanceof Projectile;
+ this.criticalStrike = criticalStrike;
+ this.isCustomDamage = isCustomDamage;
+ this.damageModifier = damageModifier;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ entityDamageByEntityEvent.setCancelled(b);
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobDamagedByPlayerEventFilter implements Listener {
+ private static final HashMap playerHitCooldownHashMap = new HashMap<>();
+ private static int clock = 0;
+
+ public static void execute(EliteMobDamagedByPlayerEvent event) {
+ event.getEliteMobEntity().addDamager(event.getPlayer(), event.getDamage());
+ }
+
+ /**
+ * Calculates Player -> EliteMobs damage.
+ *
+ * @param player Player object
+ * @return
+ */
+ private static double finalDamageCalculator(double playerWeaponTier, Player player, EliteEntity eliteEntity, boolean ranged, double damageModifier) {
+ double finalDamage;
+ if (!ranged)
+ finalDamage = getCooledAttackStrength(player) *
+ (playerWeaponTier + secondaryEnchantmentDamageIncrease(player, eliteEntity.getLivingEntity())) *
+ MobCombatSettingsConfig.getDamageToEliteMultiplier();
+ else
+ finalDamage = (playerWeaponTier + secondaryEnchantmentDamageIncrease(player, eliteEntity.getLivingEntity())) *
+ MobCombatSettingsConfig.getDamageToEliteMultiplier();
+
+ finalDamage *= damageModifier;
+
+ return Math.max(finalDamage, 1D);
+ }
+
+ /**
+ * Calculates the cooldown debuff following vanilla Minecraft rules and then linearly applies a debuff to attacks
+ *
+ * @param player Player in cooldown
+ * @return Debuff multiplier
+ */
+ private static float getCooledAttackStrength(Player player) {
+ if (!playerHitCooldownHashMap.containsKey(player)) {
+ playerHitCooldownHashMap.put(player, clock);
+ return 1;
+ }
+ float swingDelay = clock - playerHitCooldownHashMap.get(player);
+ float cooldownPeriod = getCooldownPeriod(player);
+ if (swingDelay > cooldownPeriod) return 1;
+ return swingDelay / cooldownPeriod;
+ }
+
+ /**
+ * Calculates the cooldown following vanilla rules
+ *
+ * @param player
+ * @return
+ */
+ private static float getCooldownPeriod(Player player) {
+ return (float) (1.0D / player.getAttribute(Attribute.GENERIC_ATTACK_SPEED).getValue() * 20.0D);
+ }
+
+ public static void launchInternalClock() {
+ new BukkitRunnable() {
+
+ @Override
+ public void run() {
+ if (clock == Integer.MAX_VALUE) clock = 0;
+ clock++;
+ }
+
+ }.runTaskTimer(MetadataHandler.PLUGIN, 1, 1);
+ }
+
+ private static double secondaryEnchantmentDamageIncrease(Player player, LivingEntity eliteMob) {
+
+ if (eliteMob instanceof Spider || eliteMob instanceof Silverfish)
+ return ElitePlayerInventory.playerInventories.get(player.getUniqueId()).mainhand.getDamageArthropodsLevel(player.getInventory().getItemInMainHand(), false);
+ if (eliteMob instanceof Zombie || eliteMob instanceof Skeleton)
+ return ElitePlayerInventory.playerInventories.get(player.getUniqueId()).mainhand.getDamageUndeadLevel(player.getInventory().getItemInMainHand(), false);
+
+ return 0;
+
+ }
+
+ private static boolean isCriticalHit(Player player) {
+ double criticalStrike = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getCritChance(false);
+ criticalStrike += (GuildRank.critBonusValue(GuildRank.getGuildPrestigeRank(player), GuildRank.getActiveGuildRank(player)) / 100);
+ return ThreadLocalRandom.current().nextDouble() < criticalStrike;
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onEliteMobAttack(EntityDamageByEntityEvent event) {
+ if (event.getEntity().getType().equals(EntityType.ENDER_DRAGON) &&
+ ((EnderDragon) event.getEntity()).getPhase().equals(EnderDragon.Phase.DYING))
+ return;
+ LivingEntity livingEntity = EntityFinder.filterRangedDamagers(event.getDamager());
+ if (livingEntity == null) return;
+ if (!livingEntity.getType().equals(EntityType.PLAYER)) return;
+ Player player = (Player) livingEntity;
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ //Living entity is sometimes null when the damage is dealt to an already dead entity - might happen with mcmmo due to DOTs and stuff
+ if (eliteEntity == null || !eliteEntity.isValid()) return;
+ //If the damage wasn't caused by an elite item, just allow the event to go as raw
+ EliteMobDamagedByPlayerEvent eliteMobDamagedByPlayerEvent;
+ double damage;
+ //Thorns overrides all other possible damage
+ if (event.getCause().equals(EntityDamageEvent.DamageCause.THORNS)) {
+ int thornsLevel = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getThornsLevel();
+ Strike strike = new Strike(thornsLevel, false, true, 1);
+ eliteMobDamagedByPlayerEvent = new EliteMobDamagedByPlayerEvent(eliteEntity,
+ player,
+ event,
+ strike.damage,
+ strike.criticalStrike,
+ strike.customDamage,
+ strike.damageModifier);
+ damage = strike.damage;
+ } else if ((event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK) ||
+ event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_SWEEP_ATTACK) ||
+ event.getCause().equals(EntityDamageEvent.DamageCause.PROJECTILE)) &&
+ EliteMobsItemDetector.isEliteMobsItem(player.getInventory().getItemInMainHand())) {
+ Strike strike = getDamage(player, eliteEntity, event);
+ eliteMobDamagedByPlayerEvent = new EliteMobDamagedByPlayerEvent(eliteEntity,
+ player,
+ event,
+ strike.damage,
+ strike.criticalStrike,
+ strike.customDamage,
+ strike.damageModifier);
+ damage = strike.damage;
+ } else {
+ //Runs if the damage was not dealt by an elite item, important for other plugins
+ eliteMobDamagedByPlayerEvent = new EliteMobDamagedByPlayerEvent(eliteEntity,
+ player,
+ event,
+ event.getFinalDamage(),
+ false,
+ false,
+ 1);
+ damage = event.getDamage();
+ }
+
+ damage = Round.twoDecimalPlaces(damage);
+
+ new EventCaller(eliteMobDamagedByPlayerEvent);
+ if (eliteMobDamagedByPlayerEvent.isCancelled) {
+ event.setCancelled(true);
+ return;
+ }
+ execute(eliteMobDamagedByPlayerEvent);
+
+ //nullify vanilla reductions
+ for (EntityDamageEvent.DamageModifier modifier : EntityDamageByEntityEvent.DamageModifier.values())
+ if (event.isApplicable(modifier))
+ event.setDamage(modifier, 0);
+
+ if (eliteEntity.getLivingEntity() != null)
+ if (eliteEntity.getLivingEntity().getType().equals(EntityType.ENDER_DRAGON)) {
+ if (eliteEntity.getLivingEntity().getHealth() - damage < 1) {
+ if (eliteEntity.isDying())
+ return;
+ damage = 0;
+ event.setCancelled(true);
+ ((EnderDragon) eliteEntity.getLivingEntity()).setPhase(EnderDragon.Phase.DYING);
+ eliteEntity.setDying(true);
+ //remove the dragon after it is done with the light show, this death doesn't show up on events
+ Bukkit.getScheduler().runTaskLater(MetadataHandler.PLUGIN, () -> new EventCaller(new EliteMobDeathEvent(eliteEntity)), 200);
+ }
+ }
+
+ event.setDamage(EntityDamageEvent.DamageModifier.BASE, damage);
+ eliteEntity.syncPluginHealth(((LivingEntity) event.getEntity()).getHealth());
+
+ //No antiexploit checks for dungeons
+ if (!(EliteMobs.worldGuardIsEnabled &&
+ !WorldGuardFlagChecker.checkFlag(
+ eliteEntity.getLivingEntity().getLocation(),
+ WorldGuardCompatibility.getEliteMobsAntiExploitFlag())))
+ if (event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK))
+ if (!eliteEntity.isInAntiExploitCooldown())
+ Bukkit.getServer().getPluginManager().callEvent(
+ new EliteMobDamagedByPlayerAntiExploitEvent(eliteEntity, eliteMobDamagedByPlayerEvent));
+ }
+
+ public Strike getDamage(Player player, EliteEntity eliteEntity, EntityDamageByEntityEvent event) {
+ //citizens
+ if (player.hasMetadata("NPC")) {
+ return new Strike(DamageEliteMob.getDamageValue(eliteEntity, DamageEliteMob.DamageAmount.LOW), false, true, 1);
+ }
+
+ //if the damage source is custom , the damage is final
+ if (CombatSystem.bypass) {
+ double rawDamage = event.getDamage();
+ CombatSystem.bypass = false;
+ return new Strike(rawDamage, false, true, 1);
+ }
+
+ double playerWeaponTier;
+ //Melee attacks dealt with ranged weapons should have a tier of 0
+ if (!(event.getDamager() instanceof Arrow) &&
+ (player.getInventory().getItemInMainHand().getType().equals(Material.BOW) ||
+ player.getInventory().getItemInMainHand().getType().equals(Material.CROSSBOW)))
+ playerWeaponTier = 0;
+ else
+ playerWeaponTier = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getWeaponTier(true);
+
+ double damageModifier = 1;
+ if (eliteEntity instanceof CustomBossEntity)
+ damageModifier = ((CustomBossEntity) eliteEntity).getDamageModifier(player.getInventory().getItemInMainHand().getType());
+
+ double newDamage = finalDamageCalculator(playerWeaponTier, player, eliteEntity, event.getDamager() instanceof Arrow, damageModifier);
+
+ if (event.getDamager() instanceof Arrow) {
+ //note: the arrow velocity amplitude at full load is about 2.8
+ double arrowSpeedMultiplier = Math.sqrt(Math.pow(event.getDamager().getVelocity().getX(), 2D) +
+ Math.pow(event.getDamager().getVelocity().getY(), 2D) +
+ Math.pow(event.getDamager().getVelocity().getZ(), 2D));
+ arrowSpeedMultiplier = Math.min(arrowSpeedMultiplier, 2.8D);
+ arrowSpeedMultiplier = arrowSpeedMultiplier / 2.8D;
+ newDamage *= arrowSpeedMultiplier;
+ }
+
+ boolean criticalHit = isCriticalHit(player);
+
+ if (criticalHit) newDamage += newDamage * 0.5;
+
+ return new Strike(newDamage, criticalHit, false, damageModifier);
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (!(event.getAction().equals(Action.LEFT_CLICK_AIR) || event.getAction().equals(Action.LEFT_CLICK_BLOCK) ||
+ event.getAction().equals(Action.PHYSICAL))) return;
+ playerHitCooldownHashMap.put(event.getPlayer(), clock);
+
+ }
+
+ private static class Strike {
+ @Getter
+ private final double damage;
+ @Getter
+ private final boolean criticalStrike;
+ @Getter
+ private final boolean customDamage;
+ @Getter
+ private final double damageModifier;
+
+ public Strike(double damage, boolean criticalStrike, boolean customDamage, double damageModifier) {
+ this.damage = damage;
+ this.criticalStrike = criticalStrike;
+ this.customDamage = customDamage;
+ this.damageModifier = damageModifier;
+ }
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java
new file mode 100644
index 000000000..bd4a4f8a2
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java
@@ -0,0 +1,89 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.EliteMobs;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardFlagChecker;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.*;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class EliteMobDamagedEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final EntityDamageEvent entityDamageEvent;
+ private boolean isCancelled = false;
+
+ public EliteMobDamagedEvent(EliteEntity eliteEntity, EntityDamageEvent event) {
+ this.entity = eliteEntity.getLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.entityDamageEvent = event;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return eliteEntity;
+ }
+
+ public EntityDamageEvent getEntityDamageEvent() {
+ return entityDamageEvent;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ entityDamageEvent.setCancelled(b);
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobDamageEventFilter implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGH)
+ public void onEntityDamageByEntityEvent(EntityDamageEvent event) {
+
+ if (event.isCancelled()) return;
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+
+ EliteMobDamagedEvent eliteMobDamagedEvent = new EliteMobDamagedEvent(eliteEntity, event);
+ new EventCaller(eliteMobDamagedEvent);
+ if (eliteMobDamagedEvent.isCancelled) {
+ eliteMobDamagedEvent.setCancelled(true);
+ return;
+ }
+
+ //happens if it dies
+ if (!eliteEntity.isValid()) return;
+
+ if (EliteMobs.worldGuardIsEnabled && !WorldGuardFlagChecker.checkFlag(eliteEntity.getLivingEntity().getLocation(),
+ WorldGuardCompatibility.getEliteMobsAntiExploitFlag()))
+ return;
+
+ Bukkit.getServer().getPluginManager().callEvent(new GenericAntiExploitEvent(eliteEntity, event));
+
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDeathEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDeathEvent.java
new file mode 100644
index 000000000..7ed9ca552
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDeathEvent.java
@@ -0,0 +1,70 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDeathEvent;
+
+public class EliteMobDeathEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private EntityDeathEvent entityDeathEvent = null;
+
+ public EliteMobDeathEvent(EliteEntity eliteEntity, EntityDeathEvent entityDeathEvent) {
+ this.entity = eliteEntity.getUnsyncedLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.entityDeathEvent = entityDeathEvent;
+ eliteEntity.remove(RemovalReason.DEATH);
+ }
+
+ /**
+ * This is necessary for End Dragons
+ *
+ * @param eliteEntity
+ */
+ public EliteMobDeathEvent(EliteEntity eliteEntity) {
+ this.entity = eliteEntity.getUnsyncedLivingEntity();
+ this.eliteEntity = eliteEntity;
+ new EventCaller(new EliteMobRemoveEvent(eliteEntity, RemovalReason.DEATH));
+ }
+
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return this.entity;
+ }
+
+ public EliteEntity getEliteEntity() {
+ return this.eliteEntity;
+ }
+
+ public EntityDeathEvent getEntityDeathEvent() {
+ return this.entityDeathEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobDeathEventFilter implements Listener {
+ @EventHandler
+ public void onMobDeath(EntityDeathEvent event) {
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+ new EventCaller(new EliteMobDeathEvent(eliteEntity, event));
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java
new file mode 100644
index 000000000..1cb1eae8d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java
@@ -0,0 +1,100 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.config.DefaultConfig;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.utils.CommandRunner;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Mob;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+
+import java.util.ArrayList;
+
+public class EliteMobEnterCombatEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Player targetEntity;
+ private final EliteEntity eliteEntity;
+
+ public EliteMobEnterCombatEvent(EliteEntity eliteEntity, Player targetEntity) {
+ this.targetEntity = targetEntity;
+ this.eliteEntity = eliteEntity;
+ eliteEntity.setInCombat(true);
+ if (!DefaultConfig.isAlwaysShowNametags())
+ eliteEntity.setNameVisible(true);
+ if (eliteEntity instanceof CustomBossEntity)
+ CommandRunner.runCommandFromList(((CustomBossEntity) eliteEntity).getCustomBossesConfigFields().getOnCombatEnterCommands(), new ArrayList<>());
+ Bukkit.getScheduler().runTaskTimer(MetadataHandler.PLUGIN, (task) -> {
+ if (!eliteEntity.isValid()) {
+ task.cancel();
+ new EventCaller(new EliteMobExitCombatEvent(eliteEntity, EliteMobExitCombatEvent.EliteMobExitCombatReason.ELITE_NOT_VALID));
+ return;
+ }
+ if (!eliteEntity.isInCombatGracePeriod())
+ if (((Mob) eliteEntity.getLivingEntity()).getTarget() == null) {
+ double followRange = eliteEntity.getLivingEntity().getAttribute(Attribute.GENERIC_FOLLOW_RANGE).getValue();
+ if (eliteEntity.getLivingEntity().getType().equals(EntityType.ENDER_DRAGON))
+ followRange = 200;
+ for (Entity entity : eliteEntity.getLivingEntity().getNearbyEntities(followRange,followRange,followRange)) {
+ if (entity instanceof Player) {
+ if (((Player) entity).getGameMode().equals(GameMode.SPECTATOR))
+ continue;
+ return;
+ }
+ }
+ task.cancel();
+ new EventCaller(new EliteMobExitCombatEvent(eliteEntity, EliteMobExitCombatEvent.EliteMobExitCombatReason.NO_NEARBY_PLAYERS));
+ }
+ }, 20L, 20L);
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Player getTargetEntity() {
+ return this.targetEntity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobEnterCombatEventFilter implements Listener {
+ @EventHandler(ignoreCancelled = true)
+ public void onEliteMobDamaged(EliteMobDamagedByPlayerEvent event) {
+ if (event.getEliteMobEntity().isInCombat()) return;
+ if (!(event.getEliteMobEntity().getLivingEntity() instanceof Mob)) return;
+ Bukkit.getServer().getPluginManager().callEvent(new EliteMobEnterCombatEvent(event.getEliteMobEntity(), event.getPlayer()));
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onEliteMobDamage(PlayerDamagedByEliteMobEvent event) {
+ if (event.getEliteMobEntity().isInCombat()) return;
+ if (!(event.getEliteMobEntity().getLivingEntity() instanceof Mob)) return;
+ Bukkit.getServer().getPluginManager().callEvent(new EliteMobEnterCombatEvent(event.getEliteMobEntity(), event.getPlayer()));
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onEliteMobTarget(EliteMobTargetPlayerEvent event) {
+ if (event.getEliteMobEntity().isInCombat()) return;
+ if (!(event.getEliteMobEntity().getLivingEntity() instanceof Mob)) return;
+ Bukkit.getServer().getPluginManager().callEvent(new EliteMobEnterCombatEvent(event.getEliteMobEntity(), event.getPlayer()));
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobExitCombatEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobExitCombatEvent.java
new file mode 100644
index 000000000..70b4409d7
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobExitCombatEvent.java
@@ -0,0 +1,62 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.config.DefaultConfig;
+import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.utils.CommandRunner;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.ArrayList;
+
+public class EliteMobExitCombatEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final EliteEntity eliteEntity;
+ private final EliteMobExitCombatReason eliteMobExitCombatReason;
+
+
+ public EliteMobExitCombatEvent(EliteEntity eliteEntity, EliteMobExitCombatReason reason) {
+ this.eliteEntity = eliteEntity;
+ this.eliteMobExitCombatReason = reason;
+ eliteEntity.setInCombat(false);
+ if (eliteEntity.getUnsyncedLivingEntity().isDead()) return;
+ //only run commands if the reason for leaving combat isn't death, onDeath commands exist for that case
+ if (eliteEntity instanceof CustomBossEntity)
+ CommandRunner.runCommandFromList(((CustomBossEntity) eliteEntity).getCustomBossesConfigFields().getOnCombatLeaveCommands(), new ArrayList<>());
+ if (eliteEntity.isValid() &&
+ MobCombatSettingsConfig.isRegenerateCustomBossHealthOnCombatEnd() &&
+ !reason.equals(EliteMobExitCombatReason.PHASE_SWITCH) &&
+ !eliteEntity.getUnsyncedLivingEntity().getType().equals(EntityType.PHANTOM))
+ eliteEntity.fullHeal();
+ if (!DefaultConfig.isAlwaysShowNametags())
+ eliteEntity.setNameVisible(false);
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ public EliteMobExitCombatReason getEliteMobExitCombatReason() {
+ return eliteMobExitCombatReason;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public enum EliteMobExitCombatReason {
+ NO_NEARBY_PLAYERS,
+ SPIRIT_WALK,
+ ELITE_NOT_VALID,
+ PHASE_SWITCH
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobHealEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobHealEvent.java
new file mode 100644
index 000000000..e80d6e71c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobHealEvent.java
@@ -0,0 +1,49 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import lombok.Getter;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class EliteMobHealEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final EliteEntity eliteEntity;
+ @Getter
+ private double healAmount = 0;
+ private boolean isCancelled = false;
+ @Getter
+ private boolean fullHeal = false;
+
+ public EliteMobHealEvent(EliteEntity eliteEntity, double healAmount) {
+ this.eliteEntity = eliteEntity;
+ this.healAmount = healAmount;
+ }
+
+ public EliteMobHealEvent(EliteEntity eliteEntity, boolean fullHeal) {
+ this.eliteEntity = eliteEntity;
+ this.fullHeal = fullHeal;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobRemoveEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobRemoveEvent.java
new file mode 100644
index 000000000..452486484
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobRemoveEvent.java
@@ -0,0 +1,49 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class EliteMobRemoveEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final RemovalReason removalReason;
+
+ /**
+ * This is always the last event to be called when an Elite Mob dies, and is used to clean up references to it in memory.
+ *
+ * @param eliteEntity Elite Mob removed
+ * @param removalReason Reason for removal
+ */
+ public EliteMobRemoveEvent(EliteEntity eliteEntity, RemovalReason removalReason) {
+ this.entity = eliteEntity.getUnsyncedLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.removalReason = removalReason;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return this.entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ public RemovalReason getRemovalReason() {
+ return removalReason;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobSpawnEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobSpawnEvent.java
new file mode 100644
index 000000000..3e95484b6
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobSpawnEvent.java
@@ -0,0 +1,90 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+public class EliteMobSpawnEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity livingEntity;
+ private final EliteEntity eliteEntity;
+ private final CreatureSpawnEvent.SpawnReason spawnReason;
+ private boolean isCancelled = false;
+
+ /**
+ * Cancelling this event will prevent the Elite Mob from being constructed by removing it and the entity it would've converted
+ *
+ * @param eliteEntity EliteMobEntity being formed
+ */
+ public EliteMobSpawnEvent(EliteEntity eliteEntity) {
+ this.livingEntity = eliteEntity.getLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.spawnReason = eliteEntity.getSpawnReason();
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns the entity being converted to an EliteMobEntity
+ *
+ * @return Entity being converted into an Elite Mob
+ */
+ public LivingEntity getEntity() {
+ return this.livingEntity;
+ }
+
+ /**
+ * Returns the EliteMobEntity currently being formed
+ *
+ * @return EliteMobEntity currently being formed
+ */
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ /**
+ * Gets the reason for the Entity getting spawned
+ *
+ * @return Reason for the Entity getting spawned
+ */
+ public CreatureSpawnEvent.SpawnReason getReason() {
+ return this.spawnReason;
+ }
+
+ /**
+ * Returns if the event is cancelled
+ *
+ * @return If the event is cancelled
+ */
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ /**
+ * Cancels the event. This will cancel the formation of the Elite Mob and remove the living entity. Once cancelled it can't be uncancelled.
+ *
+ * @param cancel Cancels the event
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.isCancelled = cancel;
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobTargetPlayerEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobTargetPlayerEvent.java
new file mode 100644
index 000000000..220fc5fa4
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobTargetPlayerEvent.java
@@ -0,0 +1,68 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+
+public class EliteMobTargetPlayerEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final Player player;
+ private final EntityTargetLivingEntityEvent entityTargetLivingEntityEvent;
+
+ public EliteMobTargetPlayerEvent(EliteEntity eliteEntity, Player player, EntityTargetLivingEntityEvent event) {
+ this.entity = event.getEntity();
+ this.eliteEntity = eliteEntity;
+ this.player = player;
+ this.entityTargetLivingEntityEvent = event;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return this.entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ public Player getPlayer() {
+ return this.player;
+ }
+
+ public EntityTargetLivingEntityEvent entityTargetLivingEntityEvent() {
+ return this.entityTargetLivingEntityEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class EliteMobTargetPlayerEventFilter implements Listener {
+ @EventHandler
+ public void onMobTarget(EntityTargetLivingEntityEvent event) {
+ if (!(event.getTarget() instanceof Player)) return;
+ Player player = (Player) event.getTarget();
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+
+ if (player.getGameMode().equals(GameMode.ADVENTURE) || player.getGameMode().equals(GameMode.SURVIVAL))
+ Bukkit.getServer().getPluginManager().callEvent(new EliteMobTargetPlayerEvent(eliteEntity, player, event));
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobsItemDetector.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobsItemDetector.java
new file mode 100644
index 000000000..384cb6a41
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobsItemDetector.java
@@ -0,0 +1,40 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.items.customenchantments.SoulbindEnchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.jetbrains.annotations.NotNull;
+
+import javax.annotation.Nullable;
+
+public class EliteMobsItemDetector {
+
+ public static boolean isEliteMobsItem(ItemStack itemStack) {
+ return ItemTagger.isEliteItem(itemStack);
+ }
+
+ /**
+ * Returns whether an item meta has the soulbind enchantment
+ *
+ * @param itemMeta Item meta to be evaluated
+ * @return Whether the item has the soulbind meta
+ */
+ @Nullable
+ public static boolean hasSoulbindEnchantment(@NotNull ItemMeta itemMeta) {
+ return SoulbindEnchantment.itemHasSoulbindEnchantment(itemMeta);
+ }
+
+ /**
+ * Gets the {@link Player} to whom the item meta is linked.
+ *
+ * @param itemMeta Item meta to be evaluated.
+ * @return Player to whom the meta is linked. Returns null if no player is linked, or if the player linked is not online.
+ */
+ @Nullable
+ public static Player getSoulboundPlayer(@NotNull ItemMeta itemMeta) {
+ return SoulbindEnchantment.getSoulboundPlayer(itemMeta);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/GenericAntiExploitEvent.java b/src/main/java/com/magmaguy/elitemobs/api/GenericAntiExploitEvent.java
new file mode 100644
index 000000000..30723f7ad
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/GenericAntiExploitEvent.java
@@ -0,0 +1,132 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.util.Vector;
+
+public class GenericAntiExploitEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final EntityDamageEvent entityDamageEvent;
+ public Block
+ block000, block001, block002,
+ block010, block011, block012,
+ block020, block021, block022,
+ block030, block031, block032,
+ block100, blockBelow, block102,
+ block110, ground, block112,
+ block120, headMaterial, block122,
+ block130, ceilingMaterial, block132,
+ block200, block201, block202,
+ block210, block211, block212,
+ block220, block221, block222,
+ block230, block231, block232;
+ private boolean isCancelled = false;
+ private boolean isTriggered = false;
+
+ public GenericAntiExploitEvent(EliteEntity eliteEntity, EntityDamageEvent event) {
+ this.entity = eliteEntity.getLivingEntity();
+ this.eliteEntity = eliteEntity;
+ this.entityDamageEvent = event;
+ this.isCancelled = event.isCancelled();
+ if (event.isCancelled()) return;
+ if (!eliteEntity.getLivingEntity().hasAI())
+ setCancelled(true);
+ block000 = defineMaterial(new Vector(-1, -1, -1));
+ block001 = defineMaterial(new Vector(-1, -1, 0));
+ block002 = defineMaterial(new Vector(-1, -1, 1));
+ block010 = defineMaterial(new Vector(-1, 0, -1));
+ block011 = defineMaterial(new Vector(-1, 0, 0));
+ block012 = defineMaterial(new Vector(-1, 0, 1));
+ block020 = defineMaterial(new Vector(-1, 1, -1));
+ block021 = defineMaterial(new Vector(-1, 1, 0));
+ block022 = defineMaterial(new Vector(-1, 1, 1));
+ block030 = defineMaterial(new Vector(-1, 2, -1));
+ block031 = defineMaterial(new Vector(-1, 2, 0));
+ block032 = defineMaterial(new Vector(-1, 2, 1));
+ block100 = defineMaterial(new Vector(0, -1, -1));
+ //mob floor location
+ blockBelow = defineMaterial(new Vector(0, -1, 0));
+ block102 = defineMaterial(new Vector(0, -1, 1));
+ block110 = defineMaterial(new Vector(0, 0, -1));
+ //mob ground location
+ ground = defineMaterial(new Vector(0, 0, 0));
+ block112 = defineMaterial(new Vector(0, 0, 1));
+ block120 = defineMaterial(new Vector(0, 1, -1));
+ //mob head location
+ headMaterial = defineMaterial(new Vector(0, 1, 0));
+ block122 = defineMaterial(new Vector(0, 1, 1));
+ block130 = defineMaterial(new Vector(0, 2, -1));
+ //ceiling block
+ ceilingMaterial = defineMaterial(new Vector(0, 2, 0));
+ block132 = defineMaterial(new Vector(0, 2, 1));
+ block200 = defineMaterial(new Vector(1, -1, -1));
+ block201 = defineMaterial(new Vector(1, -1, 0));
+ block202 = defineMaterial(new Vector(1, -1, 1));
+ block210 = defineMaterial(new Vector(1, 0, -1));
+ block211 = defineMaterial(new Vector(1, 0, 0));
+ block212 = defineMaterial(new Vector(1, 0, 1));
+ block220 = defineMaterial(new Vector(1, 1, -1));
+ block221 = defineMaterial(new Vector(1, 1, 0));
+ block222 = defineMaterial(new Vector(1, 1, 1));
+ block230 = defineMaterial(new Vector(1, 2, -1));
+ block231 = defineMaterial(new Vector(1, 2, 0));
+ block232 = defineMaterial(new Vector(1, 2, 1));
+
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ private Block defineMaterial(Vector offset) {
+ Location clonedLocation = entity.getLocation().getBlock().getLocation().add(new Vector(0.5, 0.5, 0.5)).clone();
+ //Location templocation = clonedLocation.clone().add(offset);
+ //new DebugBlockLocation(templocation);
+ return clonedLocation.add(offset).getBlock();
+ }
+
+ public Entity getEntity() {
+ return entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return eliteEntity;
+ }
+
+ public EntityDamageEvent getEntityDamageEvent() {
+ return entityDamageEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ public boolean isTriggered() {
+ return isTriggered;
+ }
+
+ public void setTriggered(boolean triggered) {
+ isTriggered = triggered;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/NPCEntityRemoveEvent.java b/src/main/java/com/magmaguy/elitemobs/api/NPCEntityRemoveEvent.java
new file mode 100644
index 000000000..2d8ed2b0b
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/NPCEntityRemoveEvent.java
@@ -0,0 +1,4 @@
+package com.magmaguy.elitemobs.api;
+
+public class NPCEntityRemoveEvent {
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/NPCEntitySpawnEvent.java b/src/main/java/com/magmaguy/elitemobs/api/NPCEntitySpawnEvent.java
new file mode 100644
index 000000000..dd29d735f
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/NPCEntitySpawnEvent.java
@@ -0,0 +1,77 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.npcs.NPCEntity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class NPCEntitySpawnEvent extends Event implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity livingEntity;
+ private final NPCEntity npcEntity;
+ private boolean isCancelled = false;
+
+ /**
+ * Cancelling this event will prevent the NPC from being constructed by removing it and the entity it would've converted
+ */
+ public NPCEntitySpawnEvent(LivingEntity livingEntity, NPCEntity npcEntity) {
+ this.livingEntity = livingEntity;
+ this.npcEntity = npcEntity;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns the entity being converted to an EliteMobEntity
+ *
+ * @return Entity being converted into an Elite Mob
+ */
+ public LivingEntity getLivingEntity() {
+ return this.livingEntity;
+ }
+
+ /**
+ * Returns the EliteMobEntity currently being formed
+ *
+ * @return EliteMobEntity currently being formed
+ */
+ public NPCEntity getNPCEntity() {
+ return this.npcEntity;
+ }
+
+
+ /**
+ * Returns if the event is cancelled
+ *
+ * @return If the event is cancelled
+ */
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ /**
+ * Cancels the event. This will cancel the formation of the Elite Mob and remove the living entity. Once cancelled it can't be uncancelled.
+ *
+ * @param cancel Cancels the event
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.isCancelled = cancel;
+ if (isCancelled)
+ livingEntity.remove();
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java b/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java
new file mode 100644
index 000000000..c7048852c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java
@@ -0,0 +1,114 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.combatsystem.PlayerDamagedByEliteMobHandler;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.entity.*;
+import org.bukkit.event.*;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public class PlayerDamagedByEliteMobEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Entity entity;
+ private final EliteEntity eliteEntity;
+ private final Player player;
+ private final EntityDamageByEntityEvent entityDamageByEntityEvent;
+ private final Projectile projectile;
+ private boolean isCancelled = false;
+
+ public PlayerDamagedByEliteMobEvent(EliteEntity eliteEntity, Player player, EntityDamageByEntityEvent event, Projectile projectile) {
+ this.entity = event.getEntity();
+ this.eliteEntity = eliteEntity;
+ this.player = player;
+ this.entityDamageByEntityEvent = event;
+ this.projectile = projectile;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Entity getEntity() {
+ return this.entity;
+ }
+
+ public EliteEntity getEliteMobEntity() {
+ return this.eliteEntity;
+ }
+
+ public Player getPlayer() {
+ return this.player;
+ }
+
+ public Projectile getProjectile() {
+ return projectile;
+ }
+
+ public EntityDamageByEntityEvent getEntityDamageByEntityEvent() {
+ return this.entityDamageByEntityEvent;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ entityDamageByEntityEvent.setCancelled(b);
+ }
+
+ public static class PlayerDamagedByEliteMobEventFilter implements Listener {
+
+ @EventHandler
+ public void onEliteMobAttack2(EntityDamageByEntityEvent event) {
+ if (event.isCancelled()) {
+ PlayerDamagedByEliteMobHandler.bypass = false;
+ return;
+ }
+ if (!(event.getEntity() instanceof Player)) return;
+ Player player = (Player) event.getEntity();
+
+ //citizens
+ if (player.hasMetadata("NPC"))
+ return;
+
+ Projectile projectile = null;
+
+ EliteEntity eliteEntity = null;
+ if (event.getDamager() instanceof LivingEntity)
+ eliteEntity = EntityTracker.getEliteMobEntity(event.getDamager());
+ else if (event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof LivingEntity) {
+ eliteEntity = EntityTracker.getEliteMobEntity((LivingEntity) ((Projectile) event.getDamager()).getShooter());
+ projectile = (Projectile) event.getDamager();
+ } else if (event.getDamager().getType().equals(EntityType.EVOKER_FANGS))
+ if (((EvokerFangs) event.getDamager()).getOwner() != null)
+ eliteEntity = EntityTracker.getEliteMobEntity(((EvokerFangs) event.getDamager()).getOwner());
+
+ if (eliteEntity == null) return;
+
+ //dodge chance
+ if (ThreadLocalRandom.current().nextDouble() < GuildRank.dodgeBonusValue(GuildRank.getGuildPrestigeRank(player), GuildRank.getActiveGuildRank(player)) / 100) {
+ player.sendTitle(" ", "Dodged!");
+ event.setCancelled(true);
+ return;
+ }
+
+ PlayerDamagedByEliteMobEvent playerDamagedByEliteMobEvent = new PlayerDamagedByEliteMobEvent(eliteEntity, player, event, projectile);
+ if (!playerDamagedByEliteMobEvent.isCancelled)
+ new EventCaller(playerDamagedByEliteMobEvent);
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/PlayerPreTeleportEvent.java b/src/main/java/com/magmaguy/elitemobs/api/PlayerPreTeleportEvent.java
new file mode 100644
index 000000000..263546b6d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/PlayerPreTeleportEvent.java
@@ -0,0 +1,121 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.config.CombatTagConfig;
+import com.magmaguy.elitemobs.config.TranslationConfig;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import net.md_5.bungee.api.ChatMessageType;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class PlayerPreTeleportEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Location destination;
+ private final Location originalLocation;
+ private final Player player;
+ private boolean isCancelled = false;
+
+ /**
+ * Called when a player initiates a teleport to a location. The teleport will go through 3 seconds after the event is
+ * launched, assuming it isn't cancelled by the player or via code.
+ *
+ * @param player Player that will teleport
+ * @param destination Teleport destination
+ */
+ public PlayerPreTeleportEvent(Player player, Location destination) {
+ this.player = player;
+ this.destination = destination.clone();
+ this.originalLocation = player.getLocation().clone();
+ }
+
+ public static void teleportPlayer(Player player, Location destination) {
+ if (destination.getWorld() == null) return;
+ if (CombatTagConfig.isEnableTeleportTimer())
+ new EventCaller(new PlayerPreTeleportEvent(player, destination));
+ else
+ PlayerTeleportEvent.teleportPlayer(player, destination);
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public void startTeleport() {
+ new BukkitRunnable() {
+ int timerLeft = 3;
+
+ @Override
+ public void run() {
+ if (!player.isValid()) {
+ cancel();
+ return;
+ }
+
+ if (player.getLocation().getX() != originalLocation.getX() ||
+ player.getLocation().getY() != originalLocation.getY() ||
+ player.getLocation().getZ() != originalLocation.getZ())
+ isCancelled = true;
+
+ if (isCancelled) {
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
+ TextComponent.fromLegacyText(ChatColorConverter.convert(TranslationConfig.getTeleportCancelled())));
+ cancel();
+ return;
+ }
+
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
+ TextComponent.fromLegacyText(ChatColorConverter.convert(TranslationConfig.getTeleportTimeLeft())
+ .replace("$time", timerLeft + "")));
+
+
+ if (timerLeft == 0) {
+ PlayerTeleportEvent.teleportPlayer(player, destination);
+ cancel();
+ return;
+ }
+
+ timerLeft--;
+ }
+ }.runTaskTimer(MetadataHandler.PLUGIN, 0, 20);
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public Location getDestination() {
+ return destination;
+ }
+
+ public Location getOriginalLocation() {
+ return originalLocation;
+ }
+
+ public static class PlayerPreTeleportEventEvents implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onTeleportEvent(PlayerPreTeleportEvent event) {
+ event.startTeleport();
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/PlayerTeleportEvent.java b/src/main/java/com/magmaguy/elitemobs/api/PlayerTeleportEvent.java
new file mode 100644
index 000000000..2625d05ee
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/PlayerTeleportEvent.java
@@ -0,0 +1,92 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import com.magmaguy.elitemobs.config.dungeonpackager.DungeonPackagerConfigFields;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+
+import java.util.Objects;
+
+public class PlayerTeleportEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Location destination;
+ private final Location originalLocation;
+ private final Player player;
+ private boolean isCancelled = false;
+
+ /**
+ * Event fired when players teleport due to EliteMobs. This is used for teleporting to the Adventurer's Guild and to
+ * Dungeons.
+ *
+ * @param player Player to be teleported
+ * @param destination Teleport destination
+ */
+ public PlayerTeleportEvent(Player player, Location destination) {
+ this.player = player;
+ this.destination = destination;
+ this.originalLocation = player.getLocation().clone();
+ }
+
+ public static void teleportPlayer(Player player, Location destination) {
+ new EventCaller(new PlayerTeleportEvent(player, destination));
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public Location getDestination() {
+ return destination;
+ }
+
+ public Location getOriginalLocation() {
+ return originalLocation;
+ }
+
+ public void executeTeleport() {
+ player.teleport(destination);
+ for (Minidungeon minidungeon : Minidungeon.getMinidungeons().values())
+ if (minidungeon.isInstalled() &&
+ minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType().equals(DungeonPackagerConfigFields.DungeonLocationType.WORLD) &&
+ minidungeon.getWorld() != null &&
+ minidungeon.getWorld().equals(originalLocation.getWorld()))
+ return;
+
+ if (AdventurersGuildConfig.getGuildWorldLocation() != null &&
+ Objects.equals(AdventurersGuildConfig.getGuildWorldLocation().getWorld(), originalLocation.getWorld()))
+ return;
+ PlayerData.setBackTeleportLocation(player, originalLocation);
+ }
+
+ public static class PlayerTeleportEventExecutor implements Listener {
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onPlayerTeleport(PlayerTeleportEvent event) {
+ event.executeTeleport();
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestAcceptEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestAcceptEvent.java
new file mode 100644
index 000000000..f866b7788
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestAcceptEvent.java
@@ -0,0 +1,77 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.QuestsConfig;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.quests.CustomQuest;
+import com.magmaguy.elitemobs.quests.Quest;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+
+public class QuestAcceptEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+ private boolean isCancelled = false;
+
+ public QuestAcceptEvent(Player player, Quest quest) {
+ this.player = player;
+ this.quest = quest;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ isCancelled = cancel;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class QuestAcceptEventHandler implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
+ public void questAcceptLimiter(QuestAcceptEvent event) {
+ if (PlayerData.getQuests(event.getPlayer().getUniqueId()).size() < QuestsConfig.getMaximumActiveQuests())
+ return;
+ event.setCancelled(true);
+ event.getPlayer().sendMessage(ChatColorConverter.convert(QuestsConfig.getQuestCapMessage()));
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onQuestAccept(QuestAcceptEvent event) {
+ event.getPlayer().sendMessage(QuestsConfig.getQuestJoinMessage().replace("$questName", ChatColorConverter.convert(event.getQuest().getQuestName())));
+ event.getQuest().setAccepted(true);
+ if (QuestsConfig.isUseQuestAcceptTitles())
+ event.getPlayer().sendTitle(
+ ChatColorConverter.convert(QuestsConfig.getQuestStartTitle().replace("$questName", event.getQuest().getQuestName())),
+ ChatColorConverter.convert(QuestsConfig.getQuestStartSubtitle().replace("$questName", event.getQuest().getQuestName())),
+ 20, 60, 20);
+
+ if (event.getQuest() instanceof CustomQuest) {
+ CustomQuest customQuest = (CustomQuest) event.getQuest();
+
+ customQuest.applyTemporaryPermissions(event.getPlayer());
+
+ if (!customQuest.getCustomQuestsConfigFields().getQuestAcceptDialog().isEmpty())
+ for (String dialog : customQuest.getCustomQuestsConfigFields().getQuestAcceptDialog())
+ event.getPlayer().sendMessage(dialog);
+ }
+ event.getQuest().getQuestObjectives().displayTemporaryObjectivesScoreboard(event.getPlayer());
+ PlayerData.addQuest(event.getPlayer().getUniqueId(), event.getQuest());
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestCompleteEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestCompleteEvent.java
new file mode 100644
index 000000000..ecfcd1515
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestCompleteEvent.java
@@ -0,0 +1,47 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.quests.Quest;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+
+public class QuestCompleteEvent extends Event implements Cancellable {
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+ private boolean cancelled;
+
+ public QuestCompleteEvent(Player player, Quest quest) {
+ this.player = player;
+ this.quest = quest;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ public static class QuestCompleteEventHandler implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onQuestComplete(QuestCompleteEvent event) {
+ new EventCaller(new QuestRewardEvent(event.getPlayer(), event.quest));
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestLeaveEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestLeaveEvent.java
new file mode 100644
index 000000000..d594dec48
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestLeaveEvent.java
@@ -0,0 +1,61 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.config.QuestsConfig;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.quests.CustomQuest;
+import com.magmaguy.elitemobs.quests.Quest;
+import com.magmaguy.elitemobs.quests.QuestTracking;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+import org.bukkit.permissions.PermissionAttachment;
+
+public class QuestLeaveEvent extends Event {
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+
+ public QuestLeaveEvent(Player player, Quest quest) {
+ this.player = player;
+ this.quest = quest;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class QuestLeaveEventHandler implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onQuestLeave(QuestLeaveEvent event) {
+ PlayerData.removeQuest(event.getPlayer().getUniqueId(), event.getQuest());
+ event.getPlayer().sendMessage(QuestsConfig.getQuestLeaveMessage().replace("$questName", event.getQuest().getQuestName()));
+ if (QuestsConfig.isUseQuestLeaveTitles())
+ event.getPlayer().sendTitle(
+ QuestsConfig.getQuestLeaveTitle().replace("$questName", event.getQuest().getQuestName()),
+ QuestsConfig.getQuestLeaveSubtitle().replace("$questName", event.getQuest().getQuestName()),
+ 20, 60, 20);
+ if (event.getQuest() instanceof CustomQuest) {
+ CustomQuest customQuest = (CustomQuest) event.getQuest();
+ if (!customQuest.getCustomQuestsConfigFields().getTemporaryPermissions().isEmpty()) {
+ PermissionAttachment permissionAttachment = event.getPlayer().addAttachment(MetadataHandler.PLUGIN);
+ for (String permission : customQuest.getCustomQuestsConfigFields().getTemporaryPermissions())
+ permissionAttachment.setPermission(permission, false);
+ }
+
+ if (QuestTracking.getPlayerTrackingQuests().containsKey(event.getPlayer())) {
+ QuestTracking questTracking = QuestTracking.getPlayerTrackingQuests().get(event.getPlayer());
+ if (questTracking.getCustomQuest().getCustomQuestsConfigFields().equals(customQuest.getCustomQuestsConfigFields()))
+ questTracking.stop();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestObjectivesCompletedEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestObjectivesCompletedEvent.java
new file mode 100644
index 000000000..97e37bafb
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestObjectivesCompletedEvent.java
@@ -0,0 +1,40 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.config.QuestsConfig;
+import com.magmaguy.elitemobs.quests.Quest;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+
+public class QuestObjectivesCompletedEvent extends Event {
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+
+ public QuestObjectivesCompletedEvent(Player player, Quest customQuest) {
+ this.player = player;
+ this.quest = customQuest;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class QuestObjectivesCompletedEventHandler implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onObjectivesCompleted(QuestObjectivesCompletedEvent event) {
+ if (!QuestsConfig.isRequireQuestTurnIn()) {
+ QuestCompleteEvent questCompleteEvent = new QuestCompleteEvent(event.getPlayer(), event.getQuest());
+ new EventCaller(questCompleteEvent);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestProgressionEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestProgressionEvent.java
new file mode 100644
index 000000000..df2993bac
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestProgressionEvent.java
@@ -0,0 +1,47 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.config.QuestsConfig;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.quests.Quest;
+import com.magmaguy.elitemobs.quests.QuestTracking;
+import com.magmaguy.elitemobs.quests.objectives.Objective;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.*;
+
+public class QuestProgressionEvent extends Event {
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+ @Getter
+ private final Objective objective;
+
+ public QuestProgressionEvent(Player player, Quest quest, Objective objective) {
+ this.player = player;
+ this.quest = quest;
+ this.objective = objective;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class QuestProgressionEventHandler implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onQuestProgression(QuestProgressionEvent event) {
+ event.getQuest().getQuestObjectives().updateQuestStatus(event.getPlayer().getUniqueId());
+ if (QuestsConfig.isDoQuestChatProgression())
+ event.getPlayer().sendMessage(QuestsConfig.getQuestChatProgressionMessage(event.getObjective()));
+ if (!QuestTracking.isTracking(event.player))
+ event.getQuest().getQuestObjectives().displayTemporaryObjectivesScoreboard(event.getPlayer());
+ PlayerData.updateQuestStatus(event.getPlayer().getUniqueId(), event.getQuest());
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/QuestRewardEvent.java b/src/main/java/com/magmaguy/elitemobs/api/QuestRewardEvent.java
new file mode 100644
index 000000000..2bbb8da1f
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/QuestRewardEvent.java
@@ -0,0 +1,59 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.config.QuestsConfig;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.quests.Quest;
+import lombok.Getter;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class QuestRewardEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final Player player;
+ @Getter
+ private final Quest quest;
+
+ public QuestRewardEvent(Player player, Quest quest) {
+ this.player = player;
+ this.quest = quest;
+
+ quest.getQuestObjectives().setTurnedIn(true);
+
+ doMessages();
+ doRewards();
+
+ completeQuestData();
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ private void doMessages() {
+ player.sendMessage(QuestsConfig.getQuestCompleteMessage().replace("$questName", quest.getQuestName()));
+ if (QuestsConfig.isUseQuestCompleteTitles())
+ player.sendTitle(
+ QuestsConfig.getQuestCompleteTitle().replace("$questName", quest.getQuestName()),
+ QuestsConfig.getQuestCompleteSubtitle().replace("$questName", quest.getQuestName()),
+ 20, 60, 20);
+ }
+
+ private void doRewards() {
+ //todo: add quest reward text for loot obtained
+ quest.getQuestObjectives().getQuestReward().doRewards();
+ }
+
+ private void completeQuestData() {
+ PlayerData.removeQuest(player.getUniqueId(), quest);
+ PlayerData.incrementQuestsCompleted(player.getUniqueId());
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/SuperMobDamageEvent.java b/src/main/java/com/magmaguy/elitemobs/api/SuperMobDamageEvent.java
new file mode 100644
index 000000000..10c701992
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/SuperMobDamageEvent.java
@@ -0,0 +1,72 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.*;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class SuperMobDamageEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity livingEntity;
+ private final EntityDamageEvent entityDamageEvent;
+ private boolean cancelled = false;
+
+ public SuperMobDamageEvent(LivingEntity livingEntity, EntityDamageEvent entityDamageEvent) {
+ this.livingEntity = livingEntity;
+ this.entityDamageEvent = entityDamageEvent;
+ }
+
+ public static void callEvent(LivingEntity livingEntity, EntityDamageEvent entityDamageEvent) {
+ new EventCaller(new SuperMobDamageEvent(livingEntity, entityDamageEvent));
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns the entity being converted to an EliteMobEntity
+ *
+ * @return Entity being converted into an Elite Mob
+ */
+ public LivingEntity getLivingEntity() {
+ return this.livingEntity;
+ }
+
+ public EntityDamageEvent getEntityDamageEvent() {
+ return this.entityDamageEvent;
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+ }
+
+ public static class SuperMobDamageEventFilter implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void superMobDamageFilter(EntityDamageEvent event) {
+ if (!EntityTracker.isSuperMob(event.getEntity())) return;
+ SuperMobDamageEvent superMobDamageEvent = new SuperMobDamageEvent((LivingEntity) event.getEntity(), event);
+ new EventCaller(superMobDamageEvent);
+ if (superMobDamageEvent.isCancelled()) event.setCancelled(true);
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/SuperMobDeathEvent.java b/src/main/java/com/magmaguy/elitemobs/api/SuperMobDeathEvent.java
new file mode 100644
index 000000000..3dd5bda68
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/SuperMobDeathEvent.java
@@ -0,0 +1,58 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Event;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDeathEvent;
+
+public class SuperMobDeathEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity livingEntity;
+
+ public SuperMobDeathEvent(LivingEntity livingEntity) {
+ this.livingEntity = livingEntity;
+ new SuperMobRemoveEvent(livingEntity, RemovalReason.DEATH);
+ }
+
+ public static void callEvent(LivingEntity livingEntity) {
+ new EventCaller(new SuperMobDeathEvent(livingEntity));
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns the entity being converted to an EliteMobEntity
+ *
+ * @return Entity being converted into an Elite Mob
+ */
+ public LivingEntity getLivingEntity() {
+ return this.livingEntity;
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static class SuperMobDeathEventFilter implements Listener {
+ @EventHandler
+ public void onMobDeath(EntityDeathEvent event) {
+ if (!EntityTracker.isSuperMob(event.getEntity())) return;
+ new EventCaller(new SuperMobDeathEvent(event.getEntity()));
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/SuperMobRemoveEvent.java b/src/main/java/com/magmaguy/elitemobs/api/SuperMobRemoveEvent.java
new file mode 100644
index 000000000..fba138a9d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/SuperMobRemoveEvent.java
@@ -0,0 +1,40 @@
+package com.magmaguy.elitemobs.api;
+
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import lombok.Getter;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class SuperMobRemoveEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+ @Getter
+ private final LivingEntity livingEntity;
+
+ public SuperMobRemoveEvent(LivingEntity livingEntity, RemovalReason removalReason) {
+ this.livingEntity = livingEntity;
+ EntityTracker.unregister(livingEntity, removalReason);
+ }
+
+ public static void callEvent(LivingEntity livingEntity, RemovalReason removalReason) {
+ new EventCaller(new SuperMobRemoveEvent(livingEntity, removalReason));
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/SuperMobSpawnEvent.java b/src/main/java/com/magmaguy/elitemobs/api/SuperMobSpawnEvent.java
new file mode 100644
index 000000000..bbf6ab762
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/SuperMobSpawnEvent.java
@@ -0,0 +1,61 @@
+package com.magmaguy.elitemobs.api;
+
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class SuperMobSpawnEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final LivingEntity livingEntity;
+ private boolean isCancelled = false;
+
+ public SuperMobSpawnEvent(LivingEntity livingEntity) {
+ this.livingEntity = livingEntity;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ /**
+ * Returns the entity being converted to an EliteMobEntity
+ *
+ * @return Entity being converted into an Elite Mob
+ */
+ public LivingEntity getLivingEntity() {
+ return this.livingEntity;
+ }
+
+ /**
+ * Returns if the event is cancelled
+ *
+ * @return If the event is cancelled
+ */
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ /**
+ * Cancels the event. This will cancel the formation of the Elite Mob and remove the living entity. Once cancelled it can't be uncancelled.
+ *
+ * @param cancel Cancels the event
+ */
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.isCancelled = cancel;
+ }
+
+ /**
+ * Returns a list of handlers
+ *
+ * @return List of handlers
+ */
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/internal/NewMinidungeonRelativeBossLocationEvent.java b/src/main/java/com/magmaguy/elitemobs/api/internal/NewMinidungeonRelativeBossLocationEvent.java
new file mode 100644
index 000000000..71d9ad518
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/internal/NewMinidungeonRelativeBossLocationEvent.java
@@ -0,0 +1,63 @@
+package com.magmaguy.elitemobs.api.internal;
+
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import org.bukkit.Location;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+
+public class NewMinidungeonRelativeBossLocationEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+ private final Minidungeon minidungeon;
+ private final Location relativeLocation;
+ private final Location realLocation;
+ private final CustomBossesConfigFields customBossesConfigFields;
+ private boolean isCancelled = false;
+
+ public NewMinidungeonRelativeBossLocationEvent(Minidungeon minidungeon, Location relativeLocation, Location realLocation, CustomBossesConfigFields customBossesConfigFields) {
+ this.minidungeon = minidungeon;
+ this.relativeLocation = relativeLocation;
+ this.realLocation = realLocation;
+ this.customBossesConfigFields = customBossesConfigFields;
+ if (relativeLocation == null) setCancelled(true);
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public Minidungeon getMinidungeon() {
+ return minidungeon;
+ }
+
+ public Location getRelativeLocation() {
+ return relativeLocation;
+ }
+
+ public Location getRealLocation() {
+ return realLocation;
+ }
+
+ public CustomBossesConfigFields getCustomBossConfigFields() {
+ return customBossesConfigFields;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.isCancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean b) {
+ this.isCancelled = b;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/api/internal/RemovalReason.java b/src/main/java/com/magmaguy/elitemobs/api/internal/RemovalReason.java
new file mode 100644
index 000000000..6caa686ed
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/api/internal/RemovalReason.java
@@ -0,0 +1,28 @@
+package com.magmaguy.elitemobs.api.internal;
+
+/**
+ * DEATH is used for when Elites die in a way detected correctly by EliteMobs
+ * CHUNK_UNLOAD fires when an Elite is removed due to a chunk unload. This is a true removal, so persistent Elites won't have it.
+ * WORLD_UNLOAD fires when an Elite is removed due to a World unload. Persistent Elites can't survive this.
+ * SHUTDOWN fires when a server shuts down, reload or when EliteMobs reloads
+ * OTHER fires when the reason couldn't be determined, probably a #remove() API call by another plugin
+ * EFFECT_TIMEOUT fires when either a power has ended or when an effect is done being displayed for any reason
+ */
+public enum RemovalReason {
+ DEATH,
+ PHASE_BOSS_RESET,
+ PHASE_BOSS_PHASE_END,
+ CHUNK_UNLOAD,
+ WORLD_UNLOAD,
+ SHUTDOWN,
+ EFFECT_TIMEOUT,
+ BOSS_TIMEOUT,
+ NPC_TIMEOUT,
+ OTHER,
+ UNSPECIFIED_WATCHDOG_REMOVAL,
+ REMOVE_COMMAND,
+ KILL_COMMAND,
+ REINFORCEMENT_CULL,
+ ENTITY_REPLACEMENT,
+ ARENA_RESET
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AlternativeDurabilityLoss.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AlternativeDurabilityLoss.java
new file mode 100644
index 000000000..51ad19f68
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AlternativeDurabilityLoss.java
@@ -0,0 +1,111 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.api.EliteMobsItemDetector;
+import com.magmaguy.elitemobs.config.ItemSettingsConfig;
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.items.ItemTierFinder;
+import com.magmaguy.elitemobs.utils.EntityFinder;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+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.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.player.PlayerItemDamageEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class AlternativeDurabilityLoss implements Listener {
+
+ //these values are percentual
+ private static double durabilityLoss(ItemStack itemStack) {
+ boolean isWeaponMaterial = ItemTierFinder.isWeaponMaterial(itemStack);
+ int maxDurability = itemStack.getType().getMaxDurability() > (isWeaponMaterial ? 2000 : 1000) ? (isWeaponMaterial ? 2000 : 1000) : itemStack.getType().getMaxDurability();
+ double baseModifier = isWeaponMaterial ? 2000 : 1000;
+ double durabilityLoss = ((baseModifier - maxDurability) / baseModifier) * ItemSettingsConfig.getEliteDurabilityMultiplier();
+ double durabilityLevel = 1 + (ItemTagger.getEnchantment(itemStack.getItemMeta(), Enchantment.DURABILITY.getKey()) / 4d);
+ double defaultMultiplier = 0.5; //just tweaking defaults
+ return durabilityLoss / durabilityLevel * defaultMultiplier;
+ }
+
+ private static boolean isOnLastDamage(ItemStack itemStack) {
+ if (itemStack == null) return false;
+ if (!itemStack.hasItemMeta()) return false;
+ if (!ItemTagger.isEliteItem(itemStack)) return false;
+ if (!(itemStack.getItemMeta() instanceof Damageable)) return false;
+ if (itemStack.getType().getMaxDurability() == 0) return false;
+ if (((Damageable) itemStack.getItemMeta()).getDamage() + 1 < itemStack.getType().getMaxDurability())
+ return false;
+ return true;
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void onDurabilityLoss(PlayerItemDamageEvent event) {
+ if (!EliteMobsItemDetector.isEliteMobsItem(event.getItem())) return;
+ event.setCancelled(true);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPlayerDeath(PlayerDeathEvent event) {
+ ArrayList itemsList = new ArrayList<>(Arrays.asList(event.getEntity().getInventory().getArmorContents()));
+ itemsList.add(event.getEntity().getInventory().getItemInMainHand());
+ itemsList.add(event.getEntity().getInventory().getItemInOffHand());
+
+ for (ItemStack itemStack : itemsList)
+ if (itemStack != null &&
+ itemStack.getType().getMaxDurability() != 0 &&
+ EliteMobsItemDetector.isEliteMobsItem(itemStack) &&
+ itemStack.getItemMeta() instanceof Damageable) {
+ Damageable damageable = (Damageable) itemStack.getItemMeta();
+ int maxDurability = itemStack.getType().getMaxDurability();
+ int durabilityLoss = (int) (maxDurability * durabilityLoss(itemStack));
+ int currentDurability = damageable.getDamage();
+ int newDurability = currentDurability + durabilityLoss;
+ damageable.setDamage(newDurability);
+ itemStack.setItemMeta(damageable);
+ if (newDurability >= maxDurability)
+ if (ItemSettingsConfig.isPreventEliteItemsFromBreaking()) {
+ damageable.setDamage(maxDurability - 1);
+ itemStack.setItemMeta(damageable);
+ } else
+ itemStack.setAmount(0);
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
+ public void onPlayerDamaged(EntityDamageEvent event) {
+ if (!event.getEntity().getType().equals(EntityType.PLAYER)) return;
+ //citizens spams this really hard for some reason
+ if (event.getEntity().hasMetadata("NPC")) return;
+ Player player = (Player) event.getEntity();
+ for (ItemStack itemStack : player.getInventory().getArmorContents())
+ if (isOnLastDamage(itemStack)) {
+ player.getWorld().dropItem(player.getLocation(), itemStack.clone());
+ itemStack.setAmount(0);
+ player.sendMessage(ChatColorConverter.convert(ItemSettingsConfig.getLowArmorDurabilityItemDropMessage()));
+ }
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
+ public void onPlayerDamage(EntityDamageByEntityEvent event) {
+ LivingEntity livingEntity = EntityFinder.filterRangedDamagers(event.getDamager());
+ if (livingEntity == null) return;
+ if (!livingEntity.getType().equals(EntityType.PLAYER)) return;
+ Player player = (Player) livingEntity;
+ ItemStack itemStack = player.getInventory().getItemInMainHand();
+ if (isOnLastDamage(itemStack)) {
+ player.getWorld().dropItem(player.getLocation(), itemStack.clone());
+ itemStack.setAmount(0);
+ player.sendMessage(ChatColorConverter.convert(ItemSettingsConfig.getLowWeaponDurabilityItemDropMessage()));
+ event.setCancelled(true);
+ }
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AntiExploitMessage.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AntiExploitMessage.java
deleted file mode 100644
index d77ec0b2d..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/AntiExploitMessage.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.ChatColorConverter;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
-import net.md_5.bungee.api.ChatMessageType;
-import net.md_5.bungee.api.chat.TextComponent;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-
-
-public class AntiExploitMessage {
-
- public static void sendWarning(LivingEntity livingEntity) {
-
- for (Entity entity : livingEntity.getNearbyEntities(15, 15, 15))
- if (entity instanceof Player) {
- Player player = (Player) entity;
- player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
- TextComponent.fromLegacyText(ChatColorConverter.convert(ConfigValues.mobCombatSettingsConfig.getString(MobCombatSettingsConfig.ANTI_EXPLOIT_MESSAGE))));
- }
-
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ChunkUnloadMetadataPurge.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ChunkUnloadMetadataPurge.java
deleted file mode 100644
index df545a6a9..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ChunkUnloadMetadataPurge.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.world.ChunkUnloadEvent;
-
-
-/**
- * Created by MagmaGuy on 20/12/2016.
- */
-public class ChunkUnloadMetadataPurge implements Listener {
-
- @EventHandler
- public void onUnload(ChunkUnloadEvent event) {
- EntityTracker.chunkWiper(event);
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/CombustionPrevention.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/CombustionPrevention.java
new file mode 100644
index 000000000..5491259a5
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/CombustionPrevention.java
@@ -0,0 +1,16 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityCombustEvent;
+import org.bukkit.potion.PotionEffectType;
+
+public class CombustionPrevention implements Listener {
+ @EventHandler
+ public void onCombust(EntityCombustEvent event) {
+ if (event.getEntity() instanceof LivingEntity &&
+ ((LivingEntity) event.getEntity()).hasPotionEffect(PotionEffectType.FIRE_RESISTANCE))
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EliteBlazeWaterDamagePrevention.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EliteBlazeWaterDamagePrevention.java
new file mode 100644
index 000000000..4cd3e9b86
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EliteBlazeWaterDamagePrevention.java
@@ -0,0 +1,18 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedEvent;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class EliteBlazeWaterDamagePrevention implements Listener {
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onBlazeWaterDamage(EliteMobDamagedEvent event) {
+ if (event.getEntity() == null) return;
+ if (!event.getEntity().getType().equals(EntityType.BLAZE)) return;
+ if (!event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.DROWNING)) return;
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderCrystalDamageProtectionBypass.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderCrystalDamageProtectionBypass.java
new file mode 100644
index 000000000..cf0424d5d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderCrystalDamageProtectionBypass.java
@@ -0,0 +1,20 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.utils.EntityFinder;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+
+public class EnderCrystalDamageProtectionBypass implements Listener {
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
+ if (!event.isCancelled()) return;
+ if (!event.getEntity().getType().equals(EntityType.ENDER_CRYSTAL)) return;
+ LivingEntity entity = EntityFinder.filterRangedDamagers(event.getDamager());
+ if (entity == null || !entity.getType().equals(EntityType.PLAYER)) return;
+ event.setCancelled(false);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderDragonUnstuck.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderDragonUnstuck.java
new file mode 100644
index 000000000..cf15fe3c8
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EnderDragonUnstuck.java
@@ -0,0 +1,37 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.api.EliteMobEnterCombatEvent;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.entity.EnderDragon;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Wolf;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+
+public class EnderDragonUnstuck implements Listener {
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void onDragonEnterCombat(EliteMobEnterCombatEvent event) {
+ if (event.getEliteMobEntity() == null) return;
+ if (event.getEliteMobEntity().getLivingEntity() == null) return;
+ if (!event.getEliteMobEntity().getLivingEntity().getType().equals(EntityType.ENDER_DRAGON)) return;
+ event.getEliteMobEntity().getLivingEntity().setAI(true);
+ ((EnderDragon) event.getEliteMobEntity().getLivingEntity()).setPhase(EnderDragon.Phase.LEAVE_PORTAL);
+ }
+
+ public static class AggroPrevention implements Listener {
+
+ @EventHandler(ignoreCancelled = true)
+ public void onTarget(EntityTargetLivingEntityEvent event) {
+ if (event.getEntity().getType().equals(EntityType.WOLF) && !((Wolf) event.getEntity()).isAngry() ||
+ event.getTarget() != null &&
+ event.getTarget().getType().equals(EntityType.WOLF) && !((Wolf) event.getTarget()).isAngry())
+ return;
+ if (EntityTracker.isEliteMob(event.getEntity()) && event.getTarget() != null && EntityTracker.isEliteMob(event.getTarget()) ||
+ EntityTracker.isEliteMob(event.getEntity()) && event.getTarget() != null && EntityTracker.isNPCEntity(event.getTarget()))
+ event.setCancelled(true);
+ }
+
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityDeathDataFlusher.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityDeathDataFlusher.java
deleted file mode 100644
index b402c859d..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityDeathDataFlusher.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.EventPriority;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDeathEvent;
-
-/**
- * Created by MagmaGuy on 14/07/2017.
- */
-public class EntityDeathDataFlusher implements Listener {
-
- @EventHandler(priority = EventPriority.MONITOR)
- public void onEntityDeathFlushData(EntityDeathEvent event) {
-
- EntityTracker.deathWipe(event);
-
- }
-
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityTransformHandler.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityTransformHandler.java
new file mode 100644
index 000000000..880202157
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/EntityTransformHandler.java
@@ -0,0 +1,24 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityTransformEvent;
+
+public class EntityTransformHandler implements Listener {
+
+ @EventHandler
+ public void onMobTransform(EntityTransformEvent event) {
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+ if (eliteEntity instanceof CustomBossEntity)
+ ((CustomBossEntity) eliteEntity).resetLivingEntity((LivingEntity) event.getTransformedEntity(), CreatureSpawnEvent.SpawnReason.CUSTOM);
+ else
+ eliteEntity.setLivingEntity((LivingEntity) event.getTransformedEntity(), CreatureSpawnEvent.SpawnReason.CUSTOM);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindNewWorlds.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindNewWorlds.java
new file mode 100644
index 000000000..236a57873
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindNewWorlds.java
@@ -0,0 +1,16 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.config.ValidWorldsConfig;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.world.WorldLoadEvent;
+
+public class FindNewWorlds implements Listener {
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void onWorldLoad(WorldLoadEvent event) {
+ ValidWorldsConfig.addWorld(event.getWorld().getName());
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindSuperMobs.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindSuperMobs.java
index 95ea00ed0..5e14a0ac8 100644
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindSuperMobs.java
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/FindSuperMobs.java
@@ -1,7 +1,10 @@
package com.magmaguy.elitemobs.collateralminecraftchanges;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
import com.magmaguy.elitemobs.mobconstructor.mobdata.passivemobs.SuperMobProperties;
+import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
@@ -10,11 +13,12 @@ public class FindSuperMobs implements Listener {
@EventHandler
public void findSuperMob(ChunkLoadEvent event) {
-
for (Entity entity : event.getChunk().getEntities())
- if (SuperMobProperties.isValidSuperMobType(entity)) {
- }
-
+ if (SuperMobProperties.isValidSuperMobType(entity))
+ if (((LivingEntity) entity).getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue() ==
+ SuperMobProperties.getDataInstance(entity).getSuperMobMaxHealth())
+ if (!EntityTracker.isSuperMob(entity))
+ EntityTracker.registerSuperMob((LivingEntity) entity);
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ItemEnchantmentPrevention.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ItemEnchantmentPrevention.java
new file mode 100644
index 000000000..e7174e502
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/ItemEnchantmentPrevention.java
@@ -0,0 +1,20 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.utils.ItemStackGenerator;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.PrepareAnvilEvent;
+
+public class ItemEnchantmentPrevention implements Listener {
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onResultGeneration(PrepareAnvilEvent event) {
+ if (!ItemTagger.isEliteItem(event.getInventory().getItem(0)) &&
+ !ItemTagger.isEliteItem(event.getInventory().getItem(1)))
+ return;
+ event.setResult(ItemStackGenerator.generateItemStack(Material.AIR));
+ event.getInventory().setRepairCost(300);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/KeepNeutralsAngry.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/KeepNeutralsAngry.java
new file mode 100644
index 000000000..d1f4d4d5c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/KeepNeutralsAngry.java
@@ -0,0 +1,57 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Mob;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Wolf;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashSet;
+import java.util.Objects;
+
+public class KeepNeutralsAngry {
+ private static final HashSet angryMobs = new HashSet<>();
+
+ private KeepNeutralsAngry() {
+ }
+
+ public static void showMeYouWarFace(EliteEntity eliteEntity) {
+ //might already contain
+ EntityType entityType = eliteEntity.getLivingEntity().getType();
+ if (angryMobs.contains(eliteEntity)) return;
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ //It is possible for entities to change type during combat, in which case they need to be wiped
+ if (!eliteEntity.isValid() ||
+ !entityType.equals(eliteEntity.getLivingEntity().getType()) ||
+ entityType.equals(EntityType.WOLF) && ((Wolf) eliteEntity.getLivingEntity()).isTamed()) {
+ cancel();
+ angryMobs.remove(eliteEntity);
+ return;
+ }
+
+ if (!eliteEntity.getLivingEntity().getType().equals(EntityType.LLAMA) &&
+ ((Mob) eliteEntity.getLivingEntity()).getTarget() != null)
+ return;
+
+ for (Player player : Bukkit.getOnlinePlayers())
+ if (!player.getGameMode().equals(GameMode.SPECTATOR) && !player.getGameMode().equals(GameMode.CREATIVE) &&
+ Objects.equals(player.getLocation().getWorld(), eliteEntity.getLocation().getWorld()) &&
+ player.getLocation().distance(eliteEntity.getLocation()) <
+ Objects.requireNonNull(eliteEntity.getLivingEntity().getAttribute(Attribute.GENERIC_FOLLOW_RANGE)).getBaseValue()) {
+ ((Mob) eliteEntity.getLivingEntity()).setTarget(player);
+ return;
+ }
+
+ ((Mob) eliteEntity.getLivingEntity()).setTarget(null);
+
+ }
+ }.runTaskTimer(MetadataHandler.PLUGIN, 0, 20);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/LightningSpawnBypass.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/LightningSpawnBypass.java
new file mode 100644
index 000000000..2799cd2bf
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/LightningSpawnBypass.java
@@ -0,0 +1,24 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntitySpawnEvent;
+
+public class LightningSpawnBypass implements Listener {
+ private static boolean bypass = false;
+
+ public static void bypass() {
+ bypass = true;
+ }
+
+ //This overrides region protection plugins that would delete lightning - breaking powers and effects
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onLightningSpawn(EntitySpawnEvent event) {
+ if (!bypass) return;
+ if (!event.getEntity().getType().equals(EntityType.LIGHTNING)) return;
+ bypass = true;
+ event.setCancelled(false);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PlayerDeathMessageByEliteMob.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PlayerDeathMessageByEliteMob.java
index 5acac3794..d07445d93 100644
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PlayerDeathMessageByEliteMob.java
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PlayerDeathMessageByEliteMob.java
@@ -1,24 +1,9 @@
-/*
- * 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 com.magmaguy.elitemobs.collateralminecraftchanges;
import com.magmaguy.elitemobs.ChatColorConverter;
-import com.magmaguy.elitemobs.EntityTracker;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.config.mobproperties.MobPropertiesConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.playerdata.PlayerStatsTracker;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -26,10 +11,11 @@
import org.bukkit.event.entity.PlayerDeathEvent;
import java.util.HashMap;
+import java.util.concurrent.ThreadLocalRandom;
public class PlayerDeathMessageByEliteMob implements Listener {
- private static HashMap deadPlayerList = new HashMap<>();
+ private static final HashMap deadPlayerList = new HashMap<>();
public static void addDeadPlayer(Player player, String deathMessage) {
deadPlayerList.put(player, deathMessage);
@@ -43,85 +29,23 @@ private static void removeDeadPlayer(Player player) {
deadPlayerList.remove(player);
}
- @EventHandler
- public void onPlayerDeath(PlayerDeathEvent event) {
+ public static String initializeDeathMessage(Player player, LivingEntity livingEntity) {
- if (isDeadPlayer(event.getEntity())) {
- event.setDeathMessage(deadPlayerList.get(event.getEntity()));
- removeDeadPlayer(event.getEntity());
- }
+ String deathMessage = "";
- }
-
- public static String intializeDeathMessage(Player player, LivingEntity livingEntity) {
-
- String deathMessage;
-
- /*
- Deal with players dying from Elite Mobs
- */
-
- switch (livingEntity.getType()) {
-
- case BLAZE:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.BLAZE_DEATH_MESSAGE, player, livingEntity);
- break;
- case CREEPER:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.CREEPER_DEATH_MESSAGE, player, livingEntity);
- break;
- case ENDERMAN:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.ENDERMAN_DEATH_MESSAGE, player, livingEntity);
- break;
- case ENDERMITE:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.ENDERMITE_DEATH_MESSAGE, player, livingEntity);
- break;
- case IRON_GOLEM:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.IRONGOLEM_DEATH_MESSAGE, player, livingEntity);
- break;
- case POLAR_BEAR:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.POLARBEAR_DEATH_MESSAGE, player, livingEntity);
- break;
- case SILVERFISH:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.SILVERFISH_DEATH_MESSAGE, player, livingEntity);
- break;
- case SKELETON:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.SKELETON_DEATH_MESSAGE, player, livingEntity);
- break;
- case SPIDER:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.SPIDER_DEATH_MESSAGE, player, livingEntity);
- break;
- case WITCH:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.WITCH_DEATH_MESSAGE, player, livingEntity);
- break;
- case ZOMBIE:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.ZOMBIE_DEATH_MESSAGE, player, livingEntity);
- break;
- case HUSK:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.HUSK_DEATH_MESSAGE, player, livingEntity);
- break;
- case PIG_ZOMBIE:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.ZOMBIE_PIGMAN_DEATH_MESSAGE, player, livingEntity);
- break;
- case STRAY:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.STRAY_DEATH_MESSAGE, player, livingEntity);
- break;
- case WITHER_SKELETON:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.WITHER_SKELETON_DEATH_MESSAGE, player, livingEntity);
- break;
- default:
- deathMessage = deathMessageSender(MobCombatSettingsConfig.DEFAULT_DEATH_MESSAGE, player, livingEntity);
- break;
- }
+ if (MobPropertiesConfig.getMobProperties().containsKey(livingEntity.getType()))
+ deathMessage = deathMessageSender
+ (MobPropertiesConfig.getMobProperties().get(livingEntity.getType()).getDeathMessages()
+ .get(ThreadLocalRandom.current().nextInt(MobPropertiesConfig.getMobProperties().get(livingEntity.getType()).getDeathMessages().size()))
+ , player, livingEntity);
return deathMessage;
}
- private static String deathMessageSender(String configNode, Player player, LivingEntity livingEntity) {
+ private static String deathMessageSender(String deathMessage, Player player, LivingEntity livingEntity) {
- String deathMessage = ConfigValues.mobCombatSettingsConfig.getString(configNode);
deathMessage = deathMessagePlaceholderConversion(deathMessage, player, livingEntity);
-
return deathMessage;
}
@@ -132,10 +56,21 @@ private static String deathMessagePlaceholderConversion(String deathMessage, Pla
deathMessage = deathMessage.replace("$player", player.getDisplayName());
deathMessage = deathMessage.replace("$entity", livingEntityName);
- deathMessage = ChatColorConverter.convert(deathMessage);
+ deathMessage = ChatColorConverter.convert("&7" + deathMessage);
return deathMessage;
}
+ @EventHandler
+ public void onPlayerDeath(PlayerDeathEvent event) {
+
+ if (isDeadPlayer(event.getEntity())) {
+ event.setDeathMessage(deadPlayerList.get(event.getEntity()));
+ PlayerStatsTracker.registerPlayerDeath(event.getEntity());
+ removeDeadPlayer(event.getEntity());
+ }
+
+ }
+
}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventDarkroomExploit.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventDarkroomExploit.java
deleted file mode 100644
index 650b6182f..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventDarkroomExploit.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageEvent;
-import org.bukkit.util.Vector;
-
-public class PreventDarkroomExploit implements Listener {
-
- @EventHandler
- public void onDamage(EntityDamageEvent event) {
-
- if (!EntityTracker.isNaturalEntity(event.getEntity())) return;
-
- int livingEntityCount = 1;
- for (Entity entity : event.getEntity().getNearbyEntities(1, 1, 1))
- if (entity instanceof LivingEntity)
- livingEntityCount++;
-
-
- if (livingEntityCount < 2) return;
-
- Location entityLocation = event.getEntity().getLocation().getBlock().getLocation().add(0.5, 0, 0.5);
-
- Block block1 = entityLocation.clone().add(new Vector(0, 0, 1)).getBlock();
- Block block2 = entityLocation.clone().add(new Vector(0, 0, -1)).getBlock();
- Block block3 = entityLocation.clone().add(new Vector(0, 1, 1)).getBlock();
- Block block4 = entityLocation.clone().add(new Vector(0, 1, -1)).getBlock();
- Block block5 = entityLocation.clone().add(new Vector(1, 0, 0)).getBlock();
- Block block6 = entityLocation.clone().add(new Vector(-1, 0, 0)).getBlock();
- Block block7 = entityLocation.clone().add(new Vector(1, 1, 0)).getBlock();
- Block block8 = entityLocation.clone().add(new Vector(-1, 1, 0)).getBlock();
-
- if (!block3.getType().equals(Material.AIR) && !block4.getType().equals(Material.AIR) &&
- !block7.getType().equals(Material.AIR) && !block8.getType().equals(Material.AIR)) {
- EntityTracker.unregisterNaturalEntity((LivingEntity) event.getEntity());
- Bukkit.getLogger().warning("Running");
- AntiExploitMessage.sendWarning((LivingEntity) event.getEntity());
- return;
- }
-
- int airCount = 0;
-
- if (block1.getType().equals(Material.AIR))
- airCount++;
- if (block2.getType().equals(Material.AIR))
- airCount++;
- if (block3.getType().equals(Material.AIR))
- airCount++;
- if (block4.getType().equals(Material.AIR))
- airCount++;
- if (block5.getType().equals(Material.AIR))
- airCount++;
- if (block6.getType().equals(Material.AIR))
- airCount++;
- if (block7.getType().equals(Material.AIR))
- airCount++;
- if (block8.getType().equals(Material.AIR))
- airCount++;
-
- if (airCount >= 4) return;
-
- EntityTracker.unregisterNaturalEntity((LivingEntity) event.getEntity());
- AntiExploitMessage.sendWarning((LivingEntity) event.getEntity());
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteBeeHiveEnter.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteBeeHiveEnter.java
new file mode 100644
index 000000000..1f257b4f5
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteBeeHiveEnter.java
@@ -0,0 +1,14 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityEnterBlockEvent;
+
+public class PreventEliteBeeHiveEnter implements Listener {
+ @EventHandler
+ public void onBeeEnterHive(EntityEnterBlockEvent event) {
+ if (EntityTracker.isEliteMob(event.getEntity()))
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteEquipmentDrop.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteEquipmentDrop.java
new file mode 100644
index 000000000..202e68edf
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteEquipmentDrop.java
@@ -0,0 +1,24 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.api.EliteMobDeathEvent;
+import org.bukkit.Material;
+import org.bukkit.entity.Mob;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.inventory.ItemStack;
+
+public class PreventEliteEquipmentDrop implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onEliteDeath(EliteMobDeathEvent event) {
+ if (event.getEntityDeathEvent() == null) return;
+ if (!(event.getEntity() instanceof Mob)) return;
+ if (((Mob) event.getEntity()).getEquipment() == null) return;
+ for (ItemStack drop : event.getEntityDeathEvent().getDrops())
+ for (ItemStack equipment : ((Mob) event.getEntity()).getEquipment().getArmorContents())
+ if (equipment != null && drop != null && drop.equals(equipment))
+ drop.setType(Material.AIR);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteSilverfishBlockEnter.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteSilverfishBlockEnter.java
new file mode 100644
index 000000000..ef8b4f30c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventEliteSilverfishBlockEnter.java
@@ -0,0 +1,14 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityChangeBlockEvent;
+
+public class PreventEliteSilverfishBlockEnter implements Listener {
+ @EventHandler
+ public void onSilverfishBlockEnter(EntityChangeBlockEvent event) {
+ if (EntityTracker.isEliteMob(event.getEntity()))
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventItemPickupByMobs.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventItemPickupByMobs.java
new file mode 100644
index 000000000..0b22b12c9
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventItemPickupByMobs.java
@@ -0,0 +1,16 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityPickupItemEvent;
+
+public class PreventItemPickupByMobs implements Listener {
+
+ @EventHandler
+ public void onItemPickup(EntityPickupItemEvent event) {
+ if (EntityTracker.isEliteMob(event.getEntity()))
+ event.setCancelled(true);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventMountExploit.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventMountExploit.java
deleted file mode 100644
index d5c2a5d11..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventMountExploit.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.spigotmc.event.entity.EntityMountEvent;
-
-public class PreventMountExploit implements Listener {
-
- @EventHandler
- public void mountEvent(EntityMountEvent event) {
-
- if (EntityTracker.isEliteMob(event.getEntity())) event.setCancelled(true);
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventTowerExploit.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventTowerExploit.java
deleted file mode 100644
index 2fa68dd35..000000000
--- a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventTowerExploit.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.magmaguy.elitemobs.collateralminecraftchanges;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Projectile;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.entity.EntityDamageByEntityEvent;
-import org.bukkit.util.Vector;
-
-public class PreventTowerExploit implements Listener {
-
- @EventHandler
- public void onHit(EntityDamageByEntityEvent event) {
-
- if (!(event instanceof LivingEntity)) return;
- LivingEntity livingEntity = (LivingEntity) event.getEntity();
- if (!EntityTracker.isNaturalEntity(livingEntity)) return;
- if (!(event.getDamager() instanceof Projectile &&
- ((Projectile) event.getDamager()).getShooter() instanceof Player ||
- event.getDamager() instanceof Player))
- return;
-
- Location mobLocation = event.getEntity().getLocation().add(new Vector(0.5, 0, 0.5));
- Location playerLocation;
- if (event.getDamager() instanceof Player)
- playerLocation = event.getDamager().getLocation();
- else
- playerLocation = ((Player) ((Projectile) event.getDamager()).getShooter()).getLocation().getBlock().getLocation().add(new Vector(0.5, 0, 0.5));
-
- if (playerLocation.getY() - mobLocation.getY() < 2) return;
-
- Block block1 = playerLocation.clone().add(new Vector(0, -1, 1)).getBlock();
- Block block2 = playerLocation.clone().add(new Vector(0, -1, -1)).getBlock();
- Block block3 = playerLocation.clone().add(new Vector(0, -2, 1)).getBlock();
- Block block4 = playerLocation.clone().add(new Vector(0, -2, -1)).getBlock();
- Block block5 = playerLocation.clone().add(new Vector(1, -1, 0)).getBlock();
- Block block6 = playerLocation.clone().add(new Vector(-1, -1, 0)).getBlock();
- Block block7 = playerLocation.clone().add(new Vector(1, -2, 0)).getBlock();
- Block block8 = playerLocation.clone().add(new Vector(-1, -2, 0)).getBlock();
-
- if (!(block1.getType().equals(Material.AIR) && block2.getType().equals(Material.AIR) &&
- block3.getType().equals(Material.AIR) && block4.getType().equals(Material.AIR) &&
- block5.getType().equals(Material.AIR) && block6.getType().equals(Material.AIR) &&
- block7.getType().equals(Material.AIR) && block8.getType().equals(Material.AIR)))
- return;
-
- EntityTracker.unregisterNaturalEntity(livingEntity);
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventUpgradeDiamondToNetherite.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventUpgradeDiamondToNetherite.java
new file mode 100644
index 000000000..737d72a89
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/PreventUpgradeDiamondToNetherite.java
@@ -0,0 +1,18 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.utils.ItemStackGenerator;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.PrepareSmithingEvent;
+
+public class PreventUpgradeDiamondToNetherite implements Listener {
+ @EventHandler
+ public void UpgradeItemEvent(PrepareSmithingEvent event) {
+ if (!ItemTagger.isEliteItem(event.getInventory().getItem(0)) &&
+ !ItemTagger.isEliteItem(event.getInventory().getItem(1)))
+ return;
+ event.setResult(ItemStackGenerator.generateItemStack(Material.AIR));
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/VanillaReinforcementsCanceller.java b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/VanillaReinforcementsCanceller.java
new file mode 100644
index 000000000..94d0125ac
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/collateralminecraftchanges/VanillaReinforcementsCanceller.java
@@ -0,0 +1,18 @@
+package com.magmaguy.elitemobs.collateralminecraftchanges;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+public class VanillaReinforcementsCanceller implements Listener {
+ @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
+ public void onSpawn(CreatureSpawnEvent event) {
+ if (!event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.REINFORCEMENTS)) return;
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+ event.setCancelled(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/CombatSystem.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/CombatSystem.java
new file mode 100644
index 000000000..c1b543279
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/CombatSystem.java
@@ -0,0 +1,24 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+public class CombatSystem {
+ public static final double PER_LEVEL_POWER_INCREASE = 0.5;
+ /**
+ * This determines how many hits it takes to kill a boss.
+ * Unfortunately, since it's flat, at a scale, all bosses tend to end up having the same amount of life.
+ * It accomplishes this by adding this flat amount of health to bosses.
+ */
+ public static final double TARGET_HITS_TO_KILL = 7D; //affects max health assignment on EliteMobEntity.java
+ //this sets the tier of various materials
+ public static final int TRIDENT_TIER_LEVEL = 9;
+ public static final int NETHERITE_TIER_LEVEL = 8;
+ public static final int DIAMOND_TIER_LEVEL = 7;
+ public static final int IRON_TIER_LEVEL = 6;
+ public static final int STONE_CHAIN_TIER_LEVEL = 5;
+ public static final int GOLD_WOOD_LEATHER_TIER_LEVEL = 3;
+ //this bypasses the damage system, outputting a raw damage value
+ public static boolean bypass = false;
+
+ private CombatSystem() {
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteCreeperExplosionHandler.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteCreeperExplosionHandler.java
new file mode 100644
index 000000000..f59a8804e
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteCreeperExplosionHandler.java
@@ -0,0 +1,69 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.*;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.ExplosionPrimeEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+
+import java.util.HashSet;
+
+public class EliteCreeperExplosionHandler implements Listener {
+
+ private static final HashSet explosionPlayers = new HashSet<>();
+
+ @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
+ public void onEliteCreeperDetonation(ExplosionPrimeEvent event) {
+
+ if (!(event.getEntity() instanceof Creeper && EntityTracker.isEliteMob(event.getEntity())))
+ return;
+
+ /*
+ This is necessary because the propagate the same duration as they have, which is nearly infinite
+ */
+ for (PotionEffect potionEffect : ((Creeper) event.getEntity()).getActivePotionEffects())
+ ((Creeper) event.getEntity()).removePotionEffect(potionEffect.getType());
+
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+
+ for (Entity entity : event.getEntity().getNearbyEntities(event.getRadius(), event.getRadius(), event.getRadius()))
+ if (entity.getType().equals(EntityType.PLAYER)) {
+ Player player = (Player) entity;
+ explosionPlayers.add(player);
+ ElitePlayerInventory elitePlayerInventory = ElitePlayerInventory.playerInventories.get(player.getUniqueId());
+
+ if (elitePlayerInventory == null) continue;
+ double damageReduction = 0;
+ for (ItemStack itemStack : player.getInventory().getArmorContents()) {
+ if (itemStack == null) continue;
+ for (Enchantment enchantment : itemStack.getEnchantments().keySet())
+ if (enchantment.getName().equals(Enchantment.PROTECTION_EXPLOSIONS.getName()))
+ damageReduction += PlayerDamagedByEliteMobHandler.getDamageIncreasePercentage(enchantment, itemStack);
+ }
+ damageReduction += elitePlayerInventory.baseDamageReduction();
+ double finalDamage = eliteEntity.getLevel() - damageReduction;
+ finalDamage = finalDamage < 0 ? 0 : finalDamage;
+ player.damage(finalDamage, eliteEntity.getLivingEntity());
+ } else if (entity instanceof LivingEntity)
+ ((LivingEntity) entity).damage(eliteEntity.getLevel());
+
+ }
+
+ @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
+ public void playerDamagedByExplosionEvent(EntityDamageEvent event) {
+ if (!event.getEntity().getType().equals(EntityType.PLAYER)) return;
+ if (!event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_EXPLOSION)) return;
+ Player player = (Player) event.getEntity();
+ if (!explosionPlayers.contains(player)) return;
+ explosionPlayers.remove(player);
+ event.setDamage(0);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobDamagedByEliteMobHandler.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobDamagedByEliteMobHandler.java
new file mode 100644
index 000000000..baec207fc
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobDamagedByEliteMobHandler.java
@@ -0,0 +1,29 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByEliteMobEvent;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class EliteMobDamagedByEliteMobHandler implements Listener {
+
+ @EventHandler
+ public void onIronGolemDamage(EliteMobDamagedByEliteMobEvent event) {
+
+ if (event.isCancelled()) return;
+
+ if (!(event.getDamager().getLivingEntity().getType().equals(EntityType.IRON_GOLEM) ||
+ event.getDamagee().getLivingEntity().getType().equals(EntityType.IRON_GOLEM))) return;
+
+ double damage = event.getEntityDamageByEntityEvent().getDamage() * event.getDamager().getLevel() * CombatSystem.PER_LEVEL_POWER_INCREASE;
+
+ for (EntityDamageEvent.DamageModifier modifier : EntityDamageEvent.DamageModifier.values())
+ if (event.getEntityDamageByEntityEvent().isApplicable(modifier))
+ event.getEntityDamageByEntityEvent().setDamage(modifier, 0);
+
+ event.getEntityDamageByEntityEvent().setDamage(damage);
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobGenericDamagedHandler.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobGenericDamagedHandler.java
new file mode 100644
index 000000000..ad7d38a75
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteMobGenericDamagedHandler.java
@@ -0,0 +1,21 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedEvent;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class EliteMobGenericDamagedHandler implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void eliteMobDamagedGeneric(EliteMobDamagedEvent event) {
+
+ if (event.isCancelled()) return;
+ if (event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK)) return;
+ if (!event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.CUSTOM))
+ event.getEntityDamageEvent().setDamage(EntityDamageEvent.DamageModifier.BASE, event.getEntityDamageEvent().getDamage());
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteProjectile.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteProjectile.java
new file mode 100644
index 000000000..a9f963907
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/EliteProjectile.java
@@ -0,0 +1,61 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.Location;
+import org.bukkit.NamespacedKey;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.persistence.PersistentDataType;
+import org.bukkit.projectiles.ProjectileSource;
+import org.bukkit.util.Vector;
+
+public class EliteProjectile {
+ private EliteProjectile() {
+ }
+
+ public static Projectile create(EntityType entityType, Entity shooter, Entity victim, Vector shotVector, boolean gravity) {
+ Location projectileLocation = generateLocation(shooter, victim);
+ Projectile projectile = (Projectile) projectileLocation.getWorld().spawnEntity(projectileLocation, entityType);
+ projectile.setShooter((ProjectileSource) shooter);
+ projectile.setVelocity(shotVector);
+ projectile.setGravity(gravity);
+ EntityTracker.registerProjectileEntity(projectile);
+ return projectile;
+ }
+
+ public static Projectile create(EntityType entityType, Entity shooter, Player victim, boolean gravity) {
+ Vector targetterToTargetted = victim.getEyeLocation().clone().subtract(victim.getLocation()).toVector().normalize().multiply(2);
+ return create(entityType, shooter, victim, targetterToTargetted, gravity);
+ }
+
+ public static Projectile create(EntityType entityType, Entity shooter, Vector targetterToTargetted, boolean gravity) {
+ Location projectileLocation = generateLocation(shooter, targetterToTargetted);
+ Projectile projectile = (Projectile) projectileLocation.getWorld().spawnEntity(projectileLocation, entityType);
+ projectile.setShooter((ProjectileSource) shooter);
+ projectile.setVelocity(targetterToTargetted);
+ projectile.setGravity(gravity);
+ EntityTracker.registerProjectileEntity(projectile);
+ return projectile;
+ }
+
+ private static Location generateLocation(Entity shooter, Entity victim) {
+ Vector vector = victim.getLocation().clone().subtract(shooter.getLocation().clone()).toVector().normalize();
+ return shooter.getLocation().clone().add(0, 1, 0).add(vector).setDirection(vector);
+ }
+
+ private static Location generateLocation(Entity shooter, Vector targetterToTargetted) {
+ return shooter.getLocation().clone().add(targetterToTargetted).setDirection(targetterToTargetted).add(new Vector(0, 1, 0));
+ }
+
+ public static void signExplosiveWithPower(Projectile projectile, String powerName) {
+ projectile.getPersistentDataContainer().set(new NamespacedKey(MetadataHandler.PLUGIN, "detonationPower"), PersistentDataType.STRING, powerName);
+ }
+
+ public static String readExplosivePower(Projectile projectile) {
+ return projectile.getPersistentDataContainer().get(new NamespacedKey(MetadataHandler.PLUGIN, "detonationPower"), PersistentDataType.STRING);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/PlayerDamagedByEliteMobHandler.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/PlayerDamagedByEliteMobHandler.java
new file mode 100644
index 000000000..90bffe438
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/PlayerDamagedByEliteMobHandler.java
@@ -0,0 +1,169 @@
+package com.magmaguy.elitemobs.combatsystem;
+
+import com.magmaguy.elitemobs.api.PlayerDamagedByEliteMobEvent;
+import com.magmaguy.elitemobs.collateralminecraftchanges.PlayerDeathMessageByEliteMob;
+import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.config.enchantments.EnchantmentsConfig;
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.items.MobTierCalculator;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.powers.meta.ProjectileTagger;
+import org.bukkit.Material;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.Damageable;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public class PlayerDamagedByEliteMobHandler implements Listener {
+
+ public static boolean bypass = false;
+
+ public static double getDamageIncreasePercentage(Enchantment enchantment, ItemStack weapon) {
+ double maxEnchantmentLevel = EnchantmentsConfig.getEnchantment(enchantment).getMaxLevel();
+ double currentEnchantmentLevel = weapon.getEnchantmentLevel(enchantment);
+ return currentEnchantmentLevel / maxEnchantmentLevel <= 1 ? currentEnchantmentLevel / maxEnchantmentLevel : 1;
+ }
+
+ /**
+ * EliteMobs -> player damage handler.
+ *
+ * @param event
+ */
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void eliteMobDamageHandler(PlayerDamagedByEliteMobEvent event) {
+ if (!event.getEliteMobEntity().isValid()) {
+ event.setCancelled(true);
+ return;
+ }
+
+ if (event.getEntityDamageByEntityEvent().isCancelled()) {
+ if (bypass)
+ bypass = false;
+ return;
+ }
+
+ //From this point on, the damage event is fully altered by Elite Mobs
+
+ Player player = (Player) event.getEntity();
+ if (ElitePlayerInventory.playerInventories.get(player.getUniqueId()) == null) return;
+
+ if (player.isBlocking()) {
+ if (player.getInventory().getItemInOffHand().getType().equals(Material.SHIELD)) {
+ ItemMeta itemMeta = player.getInventory().getItemInOffHand().getItemMeta();
+ Damageable damageable = (Damageable) itemMeta;
+
+ if (player.getInventory().getItemInOffHand().getItemMeta().hasEnchant(Enchantment.DURABILITY))
+ if (player.getInventory().getItemInOffHand().getItemMeta().getEnchantLevel(Enchantment.DURABILITY) / 20D > ThreadLocalRandom.current().nextDouble())
+ damageable.setDamage(damageable.getDamage() + 5);
+ player.getInventory().getItemInOffHand().setItemMeta(itemMeta);
+ if (Material.SHIELD.getMaxDurability() < damageable.getDamage())
+ player.getInventory().setItemInOffHand(null);
+ }
+
+ if (event.getEntityDamageByEntityEvent().getDamager() instanceof Projectile)
+ event.getEntityDamageByEntityEvent().getDamager().remove();
+
+ return;
+ }
+
+ //if the damage source is custom , the damage is final
+ if (bypass) {
+ bypass = false;
+ //Deal with the player getting killed
+ if (player.getHealth() - event.getEntityDamageByEntityEvent().getDamage() <= 0)
+ PlayerDeathMessageByEliteMob.addDeadPlayer(player, PlayerDeathMessageByEliteMob.initializeDeathMessage(player, event.getEliteMobEntity().getLivingEntity()));
+ return;
+ }
+
+ //if the projectile deals custom damage
+ if (event.getProjectile() != null && ProjectileTagger.projectileHasCustomDamage(event.getProjectile())) {
+ double damage = ProjectileTagger.getProjectileCustomDamage(event.getProjectile());
+ if (damage < 0) return;
+ //Set the final damage value
+ event.getEntityDamageByEntityEvent().setDamage(EntityDamageEvent.DamageModifier.BASE, damage);
+
+ //Deal with the player getting killed
+ if (player.getHealth() - event.getEntityDamageByEntityEvent().getDamage() <= 0)
+ PlayerDeathMessageByEliteMob.addDeadPlayer(player, PlayerDeathMessageByEliteMob.initializeDeathMessage(player, event.getEliteMobEntity().getLivingEntity()));
+ return;
+ }
+
+ //Determine tiers
+ double eliteTier = MobTierCalculator.findMobTier(event.getEliteMobEntity());
+ double playerTier = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getArmorTier(true);
+
+ double newDamage = eliteToPlayerDamageFormula(eliteTier, playerTier, player, event.getEliteMobEntity(), event.getEntityDamageByEntityEvent());
+
+
+ //nullify vanilla reductions
+ for (EntityDamageEvent.DamageModifier modifier : EntityDamageByEntityEvent.DamageModifier.values())
+ if (event.getEntityDamageByEntityEvent().isApplicable(modifier))
+ event.getEntityDamageByEntityEvent().setDamage(modifier, 0);
+
+ //Set the final damage value
+ event.getEntityDamageByEntityEvent().setDamage(EntityDamageEvent.DamageModifier.BASE, newDamage);
+
+ //Deal with the player getting killed
+ if (player.getHealth() - event.getEntityDamageByEntityEvent().getDamage() <= 0)
+ PlayerDeathMessageByEliteMob.addDeadPlayer(player, PlayerDeathMessageByEliteMob.initializeDeathMessage(player, event.getEliteMobEntity().getLivingEntity()));
+
+ }
+
+ private double eliteToPlayerDamageFormula(double eliteTier, double playerTier, Player player, EliteEntity eliteEntity, EntityDamageByEntityEvent event) {
+
+ /*
+ Note: all baseline damage gets divided by 2 because this damage level expects players to be wearing armor.
+ This method applies armor reduction and essentially nullifies any protection the armor gives.
+ This means that the baseline damage divided by 2 is the amount of damage a mob will deal to a player in a
+ balanced setting.
+ Regional bosses have normalized damage, so they use stats similar to a zombie's. Everything else uses their own
+ stats, which can make them vary pretty significantly in difficulty, which is pretty much intended as per Minecraft's
+ own system.
+ */
+ double baseDamage = EliteMobProperties.getBaselineDamage(eliteEntity.getLivingEntity().getType(), eliteEntity) / 2D;
+ double bonusDamage = eliteTier;
+ double damageReduction = playerTier;
+ double secondaryDamageReduction = secondaryEnchantmentDamageReduction(player, event);
+ double customBossDamageMultiplier = eliteEntity.getDamageMultiplier();
+
+ double finalDamage = (baseDamage * customBossDamageMultiplier + bonusDamage - damageReduction - secondaryDamageReduction) *
+ MobCombatSettingsConfig.getDamageToPlayerMultiplier();
+
+ double playerMaxHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
+
+ //Prevent 1-shots and players getting healed from hits
+ finalDamage = finalDamage < 1 ? 1 : finalDamage > playerMaxHealth ? playerMaxHealth - 1 : finalDamage;
+
+ return finalDamage;
+
+ }
+
+ private double secondaryEnchantmentDamageReduction(Player player, EntityDamageByEntityEvent event) {
+
+ double totalReductionLevel = 0;
+
+ for (ItemStack itemStack : player.getInventory().getArmorContents()) {
+ if (itemStack == null || itemStack.getItemMeta() == null) continue;
+ if (event.getDamager() instanceof Projectile)
+ totalReductionLevel += ItemTagger.getEnchantment(itemStack.getItemMeta(), Enchantment.PROTECTION_ENVIRONMENTAL.getKey());
+ }
+
+ totalReductionLevel = totalReductionLevel / 4 / 10;
+
+ return totalReductionLevel;
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AmbientDamageExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AmbientDamageExploit.java
new file mode 100644
index 000000000..12e0da10c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AmbientDamageExploit.java
@@ -0,0 +1,29 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.GenericAntiExploitEvent;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+
+public class AmbientDamageExploit implements Listener {
+
+ @EventHandler
+ public void onDamage(GenericAntiExploitEvent event) {
+ if (event.isCancelled()) return;
+ if (!event.getEliteMobEntity().getLivingEntity().hasAI()) return;
+ if (!(event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.HOT_FLOOR) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.CRAMMING) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.DROWNING) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.FALL) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.SUFFOCATION) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.CONTACT) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.LAVA) ||
+ event.getEntityDamageEvent().getCause().equals(EntityDamageEvent.DamageCause.DRYOUT)))
+ return;
+
+ event.getEliteMobEntity().incrementAntiExploit(1, "ambientdamageexploit");
+ event.setTriggered(true);
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AntiExploitMessage.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AntiExploitMessage.java
new file mode 100644
index 000000000..ce76c9b79
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/AntiExploitMessage.java
@@ -0,0 +1,28 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import net.md_5.bungee.api.ChatMessageType;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+
+public class AntiExploitMessage {
+
+ private AntiExploitMessage() {
+ }
+
+ public static void sendWarning(LivingEntity livingEntity, String code) {
+ for (Entity entity : livingEntity.getNearbyEntities(15, 15, 15))
+ if (entity instanceof Player) {
+ Player player = (Player) entity;
+ if (!player.isOp())
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(AntiExploitConfig.getAntiExploitMessage()));
+ else
+ player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(AntiExploitConfig.getAntiExploitMessage() + " OP-only:" + code));
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/EliteMobDamagedByPlayerAntiExploitListener.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/EliteMobDamagedByPlayerAntiExploitListener.java
new file mode 100644
index 000000000..db8d3365a
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/EliteMobDamagedByPlayerAntiExploitListener.java
@@ -0,0 +1,15 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerAntiExploitEvent;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+
+public class EliteMobDamagedByPlayerAntiExploitListener implements Listener {
+ @EventHandler(priority = EventPriority.MONITOR)
+ public void onDamage(EliteMobDamagedByPlayerAntiExploitEvent event) {
+ if (event.isTriggered()) return;
+ event.getEliteMobEntity().decrementAntiExploit(1);
+ event.getEliteMobEntity().setInAntiExploitCooldown();
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/HoneyBlockJumpExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/HoneyBlockJumpExploit.java
new file mode 100644
index 000000000..6554f3af3
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/HoneyBlockJumpExploit.java
@@ -0,0 +1,21 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.GenericAntiExploitEvent;
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import com.magmaguy.elitemobs.utils.VersionChecker;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+
+public class HoneyBlockJumpExploit implements Listener {
+
+ @EventHandler
+ public void onDamage(GenericAntiExploitEvent event) {
+ if (!AntiExploitConfig.isHoneyBlockExploit()) return;
+ if (VersionChecker.serverVersionOlderThan(15, 0)) return;
+ if (event.ground == null) return;
+ if (!event.ground.equals(Material.HONEY_BLOCK)) return;
+ event.getEliteMobEntity().incrementAntiExploit(5, "honeyexploit");
+ event.setTriggered(true);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventDarkroomExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventDarkroomExploit.java
new file mode 100644
index 000000000..a96ec515e
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventDarkroomExploit.java
@@ -0,0 +1,55 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.GenericAntiExploitEvent;
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+
+public class PreventDarkroomExploit implements Listener {
+
+ @EventHandler
+ public void onDamage(GenericAntiExploitEvent event) {
+
+ if (event.isCancelled()) return;
+
+ //gets blocks at 1 height completely surrounding the entity
+ if (AntiExploitConfig.isDarkroomAntiExploit1() && !event.block021.isPassable() &&
+ !event.block120.isPassable() &&
+ !event.block122.isPassable() &&
+ !event.block221.isPassable()) {
+ event.getEliteMobEntity().incrementAntiExploit(4, "darkroom coffin ring");
+ return;
+ }
+
+ //gets blocks at 0 height plus if there's a block on top
+ if (AntiExploitConfig.isDarkroomAntiExploit2() &&
+ (!event.block011.isPassable() || !event.block021.isPassable()) &&
+ (!event.block110.isPassable() || !event.block120.isPassable()) &&
+ (!event.block112.isPassable() || !event.block122.isPassable()) &&
+ (!event.block211.isPassable() || !event.block221.isPassable()) &&
+ !event.ceilingMaterial.isPassable()) {
+ event.getEliteMobEntity().incrementAntiExploit(4, "darkroom mine");
+ return;
+ }
+
+ if (AntiExploitConfig.isDarkroomAntiExploit3())
+ darkRoomAntiExploit3(event);
+
+ }
+
+ private void darkRoomAntiExploit3(GenericAntiExploitEvent event) {
+ int wallCount = 0;
+ if (!event.block011.isPassable() && !event.block021.isPassable())
+ wallCount++;
+ if (!event.block110.isPassable() && !event.block120.isPassable())
+ wallCount++;
+ if (!event.block112.isPassable() && !event.block122.isPassable())
+ wallCount++;
+ if (!event.block211.isPassable() && !event.block221.isPassable())
+ wallCount++;
+
+ if (wallCount >= 3)
+ event.getEliteMobEntity().incrementAntiExploit(4, "darkroom walls");
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventEndermanHeightExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventEndermanHeightExploit.java
new file mode 100644
index 000000000..0e5fea7e0
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventEndermanHeightExploit.java
@@ -0,0 +1,34 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerAntiExploitEvent;
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.entity.EntityType;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.util.Vector;
+
+public class PreventEndermanHeightExploit implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onDamage(EliteMobDamagedByPlayerAntiExploitEvent event) {
+
+ if (!AntiExploitConfig.isEndermanHeightAntiExploit()) return;
+ if (!event.getEntity().getType().equals(EntityType.ENDERMAN)) return;
+
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+
+ Block block = event.getEliteMobDamagedByPlayerEvent().getPlayer().getLocation().getBlock().getLocation().add(new Vector(0, 2, 0)).getBlock();
+ if (block.getType().equals(Material.AIR) || block.getType().equals(Material.WATER)) return;
+
+ eliteEntity.incrementAntiExploit(9, "enderman height");
+ event.setTriggered(true);
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventLargeDarkroomExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventLargeDarkroomExploit.java
new file mode 100644
index 000000000..6c8e6a546
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventLargeDarkroomExploit.java
@@ -0,0 +1,122 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerAntiExploitEvent;
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.utils.NonSolidBlockTypes;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.util.Vector;
+
+public class PreventLargeDarkroomExploit implements Listener {
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onEntityDamage(EliteMobDamagedByPlayerAntiExploitEvent event) {
+ if (event.isCancelled()) return;
+ antiHopper(event);
+ if (!event.getEliteMobEntity().getLivingEntity().getWorld().equals(event.getEliteMobDamagedByPlayerEvent().getPlayer().getWorld()))
+ return;
+
+ Vector ray = event.getEliteMobDamagedByPlayerEvent().getPlayer().getLocation().clone().subtract(event.getEliteMobEntity().getLivingEntity().getLocation()).toVector();
+ ray.normalize();
+ boolean playerIsBelow = ray.getY() < 0;
+ boolean playerIsAbove = ray.getY() > 0;
+ ray.setY(0);
+ ray.multiply(0.5);
+ Location rayTraceLocation = event.getEliteMobEntity().getLivingEntity().getLocation().clone();
+ Location eyeLevelBlockLocation, floorBlockLocation, previousFloorBlockLocation = null;
+ boolean isSlope = false;
+
+ for (int i = 0; i < 35; i++) {
+ if (event.getEliteMobEntity().getLivingEntity().getLocation().distanceSquared(event.getEliteMobDamagedByPlayerEvent().getPlayer().getLocation()) <
+ event.getEliteMobEntity().getLivingEntity().getLocation().distanceSquared(rayTraceLocation))
+ return;
+ rayTraceLocation.add(ray);
+ eyeLevelBlockLocation = rayTraceLocation.clone().add(new Vector(0, 1, 0));
+ floorBlockLocation = rayTraceLocation.clone().subtract(new Vector(0, 1, 0));
+
+ if (!NonSolidBlockTypes.isPassthrough(rayTraceLocation.getBlock().getType()) ||
+ !NonSolidBlockTypes.isPassthrough(eyeLevelBlockLocation.getBlock().getType())) {
+
+ if (!isSlope) {
+ isSlope = checkSlope(rayTraceLocation.clone(), eyeLevelBlockLocation.clone(), floorBlockLocation.clone(),
+ event.getEliteMobDamagedByPlayerEvent().getPlayer().getLocation().getY() - event.getEntity().getLocation().getBlockY());
+ if (!isSlope)
+ if (solidWall(rayTraceLocation, eyeLevelBlockLocation, event.getEliteMobEntity())) {
+ event.setTriggered(true);
+ return;
+ }
+ }
+
+ if (playerIsBelow)
+ if (previousFloorBlockLocation != null)
+ if (antiShortStairs(rayTraceLocation, floorBlockLocation, previousFloorBlockLocation)) {
+ event.getEliteMobEntity().incrementAntiExploit(11, "largeDarkroomAntiexploit3");
+ event.setTriggered(true);
+ return;
+ }
+
+ break;
+
+ }
+
+ previousFloorBlockLocation = floorBlockLocation.clone();
+
+ //new DebugBlockLocation(rayTraceLocation);
+ //new DebugBlockLocation(eyeLevelBlockLocation);
+ //new DebugBlockLocation(floorBlockLocation);
+ }
+
+ }
+
+ private void antiHopper(EliteMobDamagedByPlayerAntiExploitEvent event) {
+ if (!AntiExploitConfig.isLargeDarkroomAntiExploit1()) return;
+ if (event.getEliteMobEntity().getLivingEntity().getLocation().clone().subtract(new Vector(0, 1, 0)).getBlock().getType().equals(Material.HOPPER) ||
+ event.getEliteMobEntity().getLivingEntity().getLocation().clone().subtract(new Vector(0, 1, 0)).getBlock().getType().equals(Material.HOPPER)) {
+ event.getEliteMobEntity().incrementAntiExploit(5, "largeRoomAntiExploit1");
+ event.setTriggered(true);
+ }
+ }
+
+ /*
+ Looks if there's 2 solid blocks (player height) between the player and the entity
+ */
+ private boolean solidWall(Location footLevel, Location eyeLevel, EliteEntity eliteEntity) {
+ if (!AntiExploitConfig.isLargeDarkroomAntiExploit2()) return false;
+ if (!footLevel.getBlock().isPassable() && !eyeLevel.getBlock().isPassable()) {
+ eliteEntity.incrementAntiExploit(3, "largeDarkroomAntiexploit2 (wall)");
+ return true;
+ }
+ if (footLevel.getBlock().isPassable() && !eyeLevel.getBlock().isPassable()) {
+ eliteEntity.incrementAntiExploit(3, "largeDarkroomAntiexploit2 (window1)");
+ return true;
+ }
+ if (!footLevel.getBlock().isPassable() && eyeLevel.getBlock().isPassable() && !eyeLevel.clone().add(new Vector(0, 1, 0)).getBlock().isPassable()) {
+ eliteEntity.incrementAntiExploit(3, "largeDarkroomAntiexploit2 (window2)");
+ return true;
+ }
+ return false;
+ }
+
+ private boolean checkSlope(Location footLevel, Location eyeLevel, Location floorBlockLocation, double heightOffset) {
+ //Positive height offset: player is higher
+ //Negative height offset: elite is higher
+ //Equal height offset: player and elite are on the same level
+ if (heightOffset == 0)
+ return false;
+ if (heightOffset > 0)
+ return !footLevel.getBlock().isPassable() && eyeLevel.getBlock().isPassable() && eyeLevel.clone().add(new Vector(0, 1, 0)).getBlock().isPassable();
+ return floorBlockLocation.getBlock().isPassable() && footLevel.getBlock().isPassable() && eyeLevel.getBlock().isPassable();
+ }
+
+ private boolean antiShortStairs(Location footLevel, Location floorLevel, Location previousFloorLevel) {
+ if (!AntiExploitConfig.isLargeDarkroomAntiExploit3()) return false;
+ return !NonSolidBlockTypes.isPassthrough(footLevel.getBlock().getType()) ||
+ !NonSolidBlockTypes.isPassthrough(floorLevel.getBlock().getType()) ||
+ !NonSolidBlockTypes.isPassthrough(previousFloorLevel.getBlock().getType());
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventMountExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventMountExploit.java
new file mode 100644
index 000000000..c33e151cf
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventMountExploit.java
@@ -0,0 +1,23 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.spigotmc.event.entity.EntityMountEvent;
+
+public class PreventMountExploit implements Listener {
+
+ public static boolean bypass = false;
+
+ @EventHandler
+ public void mountEvent(EntityMountEvent event) {
+ if (bypass) {
+ bypass = false;
+ return;
+ }
+ if (!AntiExploitConfig.isMountAntiExploit()) return;
+ if (EntityTracker.isEliteMob(event.getEntity())) event.setCancelled(true);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventTowerExploit.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventTowerExploit.java
new file mode 100644
index 000000000..23ffe2317
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/antiexploit/PreventTowerExploit.java
@@ -0,0 +1,58 @@
+package com.magmaguy.elitemobs.combatsystem.antiexploit;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerAntiExploitEvent;
+import com.magmaguy.elitemobs.config.AntiExploitConfig;
+import com.magmaguy.elitemobs.utils.NonSolidBlockTypes;
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.util.Vector;
+
+public class PreventTowerExploit implements Listener {
+
+ @EventHandler
+ public void onHit(EliteMobDamagedByPlayerAntiExploitEvent event) {
+
+ if (event.isCancelled()) return;
+ if (!event.getEliteMobEntity().getLivingEntity().hasAI()) return;
+ if (!AntiExploitConfig.isTowerAntiExploit()) return;
+
+ Location mobLocation = event.getEntity().getLocation().add(new Vector(0.5, 0, 0.5));
+ Location playerLocation = event.getEliteMobDamagedByPlayerEvent().getPlayer().getLocation().getBlock().getLocation().add(new Vector(0.5, 0, 0.5));
+
+ if (event.getEliteMobDamagedByPlayerEvent().getPlayer().hasPotionEffect(PotionEffectType.LEVITATION)) return;
+ if (playerLocation.getY() - mobLocation.getY() < 2) return;
+
+ Block block1 = playerLocation.clone().add(new Vector(0, -1, 1)).getBlock();
+ Block block2 = playerLocation.clone().add(new Vector(0, -1, -1)).getBlock();
+ Block block3 = playerLocation.clone().add(new Vector(0, -2, 1)).getBlock();
+ Block block4 = playerLocation.clone().add(new Vector(0, -2, -1)).getBlock();
+ Block block5 = playerLocation.clone().add(new Vector(1, -1, 0)).getBlock();
+ Block block6 = playerLocation.clone().add(new Vector(-1, -1, 0)).getBlock();
+ Block block7 = playerLocation.clone().add(new Vector(1, -2, 0)).getBlock();
+ Block block8 = playerLocation.clone().add(new Vector(-1, -2, 0)).getBlock();
+
+ if (!(NonSolidBlockTypes.isPassthrough(block1.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block2.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block3.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block4.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block5.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block6.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block7.getType()) &&
+ NonSolidBlockTypes.isPassthrough(block8.getType())))
+ return;
+
+ //prevent triggering when the player is falling
+ if (!event.getEliteMobDamagedByPlayerEvent().getPlayer().isFlying() &&
+ NonSolidBlockTypes.isPassthrough(playerLocation.clone().add(new Vector(0, -1, 0)).getBlock().getType())) {
+ return;
+ }
+
+ event.getEliteMobEntity().incrementAntiExploit(5, "tower");
+ event.setTriggered(true);
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combattag/CombatTag.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/combattag/CombatTag.java
similarity index 68%
rename from src/main/java/com/magmaguy/elitemobs/combattag/CombatTag.java
rename to src/main/java/com/magmaguy/elitemobs/combatsystem/combattag/CombatTag.java
index a1efa636d..552341ca3 100644
--- a/src/main/java/com/magmaguy/elitemobs/combattag/CombatTag.java
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/combattag/CombatTag.java
@@ -1,10 +1,8 @@
-package com.magmaguy.elitemobs.combattag;
+package com.magmaguy.elitemobs.combatsystem.combattag;
-import com.magmaguy.elitemobs.ChatColorConverter;
-import com.magmaguy.elitemobs.EntityTracker;
import com.magmaguy.elitemobs.MetadataHandler;
import com.magmaguy.elitemobs.config.CombatTagConfig;
-import com.magmaguy.elitemobs.config.ConfigValues;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.GameMode;
@@ -14,10 +12,28 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
public class CombatTag implements Listener {
+ private static Player playerFinder(EntityDamageByEntityEvent event) {
+
+ if (event.getDamager() instanceof Player && EntityTracker.isEliteMob(event.getEntity()))
+ return (Player) event.getDamager();
+ if (event.getEntity() instanceof Player && (EntityTracker.isEliteMob(event.getEntity()) ||
+ event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof LivingEntity &&
+ EntityTracker.isEliteMob(((LivingEntity) ((Projectile) event.getDamager()).getShooter()))))
+ return (Player) event.getEntity();
+ if (event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof Player &&
+ EntityTracker.isEliteMob(event.getEntity()))
+ return (Player) ((Projectile) event.getDamager()).getShooter();
+
+ return null;
+
+ }
+
@EventHandler
public void onDamage(EntityDamageByEntityEvent event) {
@@ -31,48 +47,20 @@ public void onDamage(EntityDamageByEntityEvent event) {
if (player.isFlying()) {
player.setFlying(false);
player.spigot().sendMessage(ChatMessageType.ACTION_BAR,
- TextComponent.fromLegacyText(ChatColorConverter.convert(ConfigValues.combatTagConfig.getString(CombatTagConfig.COMBAT_TAG_MESSAGE))));
+ TextComponent.fromLegacyText(CombatTagConfig.getCombatTagMessage()));
+ player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW_FALLING, 20 * 60, 0));
new BukkitRunnable() {
@Override
public void run() {
- //TODO: introduce the featherfall potion effect for versions above 1.12.2
-// if (NameHandler.currentVersionIsUnder(13, 0)) {
if (!player.isOnline() || player.isDead())
cancel();
if (player.isOnGround()) {
- player.setFallDistance(0F);
cancel();
+ player.removePotionEffect(PotionEffectType.SLOW);
}
-// } else {
-////TODO: introduce the featherfall potion effect for versions above 1.12.2
-// if (!player.isOnline() || player.isDead())
-// player.removePotionEffect(PotionEffectType.SLOW);
-// cancel();
-// if (player.isOnGround()) {
-// player.setFallDistance(0F);
-// cancel();
-// }
-//
-// }
}
}.runTaskTimer(MetadataHandler.PLUGIN, 0, 1);
}
}
- private static Player playerFinder(EntityDamageByEntityEvent event) {
-
- if (event.getDamager() instanceof Player && EntityTracker.isEliteMob(event.getEntity()))
- return (Player) event.getDamager();
- if (event.getEntity() instanceof Player && (EntityTracker.isEliteMob(event.getEntity()) ||
- event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof LivingEntity &&
- EntityTracker.isEliteMob(((LivingEntity) ((Projectile) event.getDamager()).getShooter()))))
- return (Player) event.getEntity();
- if (event.getDamager() instanceof Projectile && ((Projectile) event.getDamager()).getShooter() instanceof Player &&
- EntityTracker.isEliteMob(event.getEntity()))
- return (Player) ((Projectile) event.getDamager()).getShooter();
-
- return null;
-
- }
-
}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/HealthDisplay.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/HealthDisplay.java
new file mode 100644
index 000000000..6d1eb1a5c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/HealthDisplay.java
@@ -0,0 +1,37 @@
+package com.magmaguy.elitemobs.combatsystem.displays;
+
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerEvent;
+import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.utils.DialogArmorStand;
+import org.bukkit.ChatColor;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+
+public class HealthDisplay implements Listener {
+
+ /*
+ Color progression: Dark green - Green - Red - Dark red
+ */
+ private static ChatColor setHealthColor(int currentHealth, int maxHealth) {
+ double healthPercentage = currentHealth * 100 / maxHealth;
+ if (healthPercentage > 75)
+ return ChatColor.DARK_GREEN;
+ if (healthPercentage > 50)
+ return ChatColor.GREEN;
+ if (healthPercentage > 25)
+ return ChatColor.RED;
+ if (healthPercentage > 0)
+ return ChatColor.DARK_RED;
+ return ChatColor.DARK_RED;
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onHit(EliteMobDamagedByPlayerEvent event) {
+ if (!MobCombatSettingsConfig.isDisplayHealthOnHit()) return;
+ int maxHealth = (int) event.getEliteMobEntity().getMaxHealth();
+ int currentHealth = (int) (event.getEliteMobEntity().getHealth() - event.getDamage());
+ DialogArmorStand.createDialogArmorStand(event.getEliteMobEntity().getLivingEntity(), setHealthColor(currentHealth, maxHealth) + "" + currentHealth + "/" + maxHealth);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/PopupDisplay.java b/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/PopupDisplay.java
new file mode 100644
index 000000000..462db729d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/combatsystem/displays/PopupDisplay.java
@@ -0,0 +1,157 @@
+package com.magmaguy.elitemobs.combatsystem.displays;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.api.EliteMobDamagedByPlayerEvent;
+import com.magmaguy.elitemobs.api.EliteMobHealEvent;
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
+import com.magmaguy.elitemobs.config.enchantments.premade.CriticalStrikesConfig;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.items.customenchantments.CriticalStrikesEnchantment;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.utils.DialogArmorStand;
+import com.magmaguy.elitemobs.utils.VisualArmorStand;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.EulerAngle;
+import org.bukkit.util.Vector;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public class PopupDisplay implements Listener {
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onHit(EliteMobDamagedByPlayerEvent event) {
+ if (!MobCombatSettingsConfig.isDisplayDamageOnHit()) return;
+
+ Location mobLocation = event.getEliteMobEntity().getLocation();
+
+ Vector offset = new Vector(ThreadLocalRandom.current().nextDouble(-2, 2), 0, ThreadLocalRandom.current().nextDouble(-2, 2));
+
+ String colorPrefix = "";
+ if (event.getDamageModifier() < 1) {
+ //resist
+ colorPrefix += MobCombatSettingsConfig.getResistTextColor();
+ DialogArmorStand.createDialogArmorStand(event.getEliteMobEntity().getUnsyncedLivingEntity(),
+ MobCombatSettingsConfig.getResistText(), offset.clone().subtract(new Vector(0, 0.2, 0)));
+ mobLocation.getWorld().playSound(mobLocation, Sound.BLOCK_ANVIL_USE, 1f, 1f);
+ if (MobCombatSettingsConfig.isDoResistEffect())
+ resistArmorStandCreator(event.getEliteMobEntity(), event.getPlayer(), Material.SHIELD);
+ } else if (event.getDamageModifier() > 1) {
+ //weak
+ colorPrefix += MobCombatSettingsConfig.getWeakTextColor();
+ DialogArmorStand.createDialogArmorStand(event.getEliteMobEntity().getUnsyncedLivingEntity(),
+ MobCombatSettingsConfig.getWeakText(), offset.clone().subtract(new Vector(0, 0.2, 0)));
+ mobLocation.getWorld().playSound(mobLocation, Sound.ENTITY_ITEM_BREAK, 1f, 1f);
+ if (MobCombatSettingsConfig.isDoWeakEffect())
+ weakArmorStandCreator(event.getEliteMobEntity(), event.getPlayer(), Material.DIAMOND_SWORD);
+ }
+ if (event.isCriticalStrike()) {
+ //crit
+ colorPrefix += CriticalStrikesConfig.getCriticalHitColor();
+ CriticalStrikesEnchantment.criticalStrikePopupMessage(event.getEliteMobEntity().getUnsyncedLivingEntity(), new Vector(0, 0.2, 0));
+ }
+
+ DialogArmorStand.createDialogArmorStand(event.getEliteMobEntity().getUnsyncedLivingEntity(), ChatColor.RED +
+ colorPrefix + "" + ChatColor.BOLD + "" + (int) event.getDamage() + "", offset);
+
+ }
+
+ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+ public void onHit(EliteMobHealEvent event) {
+ if (!MobCombatSettingsConfig.isDisplayDamageOnHit()) return;
+ if (!event.getEliteEntity().isValid()) return;
+
+ Vector offset = new Vector(ThreadLocalRandom.current().nextDouble(-1, 1), 0, ThreadLocalRandom.current().nextDouble(-1, 1));
+
+ if (event.isFullHeal()) {
+ DialogArmorStand.createDialogArmorStand(event.getEliteEntity().getUnsyncedLivingEntity(),
+ ChatColor.GREEN + "FULL HEAL!", offset.clone().subtract(new Vector(0, 0.2, 0)));
+ } else {
+ DialogArmorStand.createDialogArmorStand(event.getEliteEntity().getUnsyncedLivingEntity(),
+ ChatColor.GREEN + "" + event.getHealAmount() + " HP HEAL!", offset.clone().subtract(new Vector(0, 0.2, 0)));
+ }
+
+ }
+
+ private void resistArmorStandCreator(EliteEntity eliteEntity, Player player, Material material) {
+ if (!eliteEntity.isValid() || !player.isValid() || !eliteEntity.getLocation().getWorld().equals(player.getWorld()))
+ return;
+
+ ArmorStand armorStand = VisualArmorStand.VisualArmorStand(getResistLocation(player, eliteEntity), "Resist");
+ armorStand.getEquipment().setItemInMainHand(new ItemStack(material));
+ armorStand.addEquipmentLock(EquipmentSlot.HAND, ArmorStand.LockType.REMOVING_OR_CHANGING);
+ armorStand.setRightArmPose(new EulerAngle(Math.PI / 2d, Math.PI + Math.PI / 2d, Math.PI));
+
+ new BukkitRunnable() {
+ int counter = 0;
+
+ @Override
+ public void run() {
+ if (counter > 20 || !eliteEntity.isValid() || !player.isValid() || !eliteEntity.getLocation().getWorld().equals(player.getWorld())) {
+ EntityTracker.unregister(armorStand, RemovalReason.EFFECT_TIMEOUT);
+ cancel();
+ return;
+ }
+ armorStand.teleport(getResistLocation(player, eliteEntity));
+ counter++;
+ }
+ }.runTaskTimer(MetadataHandler.PLUGIN, 1, 1);
+ }
+
+ private Location getResistLocation(Player player, EliteEntity eliteEntity) {
+ Vector armorsStandVector = player.getLocation().subtract(eliteEntity.getLocation()).toVector().normalize().multiply(1.5);
+ Location armorStandLocation = eliteEntity.getLocation().add(armorsStandVector);
+ armorStandLocation.setDirection(armorsStandVector);
+ return armorStandLocation;
+ }
+
+ private void weakArmorStandCreator(EliteEntity eliteEntity, Player player, Material material) {
+ if (!eliteEntity.isValid() || !player.isValid() || !eliteEntity.getLocation().getWorld().equals(player.getWorld()))
+ return;
+
+ ArmorStand[] armorStands = new ArmorStand[2];
+ armorStands[0] = generateWeakArmorStand(player, eliteEntity, material, -1);
+ armorStands[1] = generateWeakArmorStand(player, eliteEntity, material, 1);
+
+ new BukkitRunnable() {
+ int counter = 0;
+
+ @Override
+ public void run() {
+ if (counter > 10 || !eliteEntity.isValid() || !player.isValid() || !eliteEntity.getLocation().getWorld().equals(player.getWorld())) {
+ EntityTracker.unregister(armorStands[0], RemovalReason.EFFECT_TIMEOUT);
+ EntityTracker.unregister(armorStands[1], RemovalReason.EFFECT_TIMEOUT);
+ cancel();
+ return;
+ }
+ for (ArmorStand armorStand : armorStands)
+ armorStand.teleport(armorStand.getLocation().add(eliteEntity.getLocation().add(new Vector(0, 0, 0))
+ .subtract(armorStand.getLocation()).toVector().normalize().multiply(.4)));
+ counter++;
+ }
+ }.runTaskTimer(MetadataHandler.PLUGIN, 1, 1);
+ }
+
+ private ArmorStand generateWeakArmorStand(Player player, EliteEntity eliteEntity, Material material, int offset) {
+ Vector armorsStandVector = player.getLocation().clone().add(new Vector(0, 2, 0)).subtract(eliteEntity.getLocation()).toVector().normalize().multiply(3.0).rotateAroundY(Math.PI / 8 * offset);
+ Location armorStandLocation = eliteEntity.getLocation().add(armorsStandVector);
+ armorStandLocation.setDirection(armorsStandVector.multiply(-1));
+ ArmorStand armorStand = VisualArmorStand.VisualArmorStand(armorStandLocation, "Weak");
+ armorStand.getEquipment().setHelmet(new ItemStack(material));
+ armorStand.addEquipmentLock(EquipmentSlot.HAND, ArmorStand.LockType.REMOVING_OR_CHANGING);
+ armorStand.setHeadPose(new EulerAngle(-Math.PI - Math.PI / 4D, Math.PI / 4D, 0));
+ return armorStand;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/AdminCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/AdminCommands.java
new file mode 100644
index 000000000..4b18a907e
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/AdminCommands.java
@@ -0,0 +1,791 @@
+package com.magmaguy.elitemobs.commands;
+
+import cloud.commandframework.ArgumentDescription;
+import cloud.commandframework.Command;
+import cloud.commandframework.arguments.CommandArgument;
+import cloud.commandframework.arguments.standard.*;
+import cloud.commandframework.bukkit.BukkitCommandManager;
+import cloud.commandframework.meta.CommandMeta;
+import cloud.commandframework.types.tuples.Triplet;
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.commands.admin.*;
+import com.magmaguy.elitemobs.commands.quests.QuestCommand;
+import com.magmaguy.elitemobs.config.ConfigurationExporter;
+import com.magmaguy.elitemobs.config.DefaultConfig;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfig;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields;
+import com.magmaguy.elitemobs.config.customtreasurechests.CustomTreasureChestsConfig;
+import com.magmaguy.elitemobs.config.npcs.NPCsConfig;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.events.TimedEvent;
+import com.magmaguy.elitemobs.items.ItemTagger;
+import com.magmaguy.elitemobs.items.customenchantments.SoulbindEnchantment;
+import com.magmaguy.elitemobs.items.customitems.CustomItem;
+import com.magmaguy.elitemobs.menus.GetLootMenu;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.transitiveblocks.TransitiveBlockCommand;
+import com.magmaguy.elitemobs.powers.meta.ElitePower;
+import com.magmaguy.elitemobs.thirdparty.discordsrv.DiscordSRVAnnouncement;
+import com.magmaguy.elitemobs.utils.DebugMessage;
+import com.magmaguy.elitemobs.utils.DiscordLinks;
+import io.leangen.geantyref.TypeToken;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Fireball;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.util.Vector;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+public class AdminCommands {
+
+ public AdminCommands(BukkitCommandManager manager, Command.Builder builder) {
+
+ // /em setup
+ manager.command(builder.literal("setup")
+ .meta(CommandMeta.DESCRIPTION, "Opens the main setup menu")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupMenuCommand((Player) commandContext.getSender())));
+
+ // /em setup done
+ manager.command(builder.literal("setup")
+ .literal("done")
+ .meta(CommandMeta.DESCRIPTION, "Stops showing messages on admin login.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> {
+ DefaultConfig.toggleSetupDone();
+ if (DefaultConfig.isSetupDone())
+ commandContext.getSender().sendMessage(ChatColorConverter.convert("&8[EliteMobs] &aEliteMobs" +
+ " will no longer send messages on login. You can do [/em setup done] again to revert this."));
+ else commandContext.getSender().sendMessage(ChatColorConverter.convert("&8[EliteMobs] &aEliteMobs" +
+ " will once again send messages on login. You can do [/em setup done] again to revert this."));
+ }));
+
+ // /em setup minidungeon
+ manager.command(builder.literal("setup")
+ .literal("minidungeon")
+ .argument(StringArgument.newBuilder("minidungeonName"), ArgumentDescription.of("minidungeon name"))
+ .meta(CommandMeta.DESCRIPTION, "Installs a Minidungeon")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupMinidungeonCommand((Player) commandContext.getSender(), commandContext.get("minidungeonName"))));
+
+ // /em setup minidungeonNoPaste
+ manager.command(builder.literal("setup")
+ .literal("minidungeonNoPaste")
+ .argument(StringArgument.newBuilder("minidungeonName"), ArgumentDescription.of("minidungeon name"))
+ .meta(CommandMeta.DESCRIPTION, "Installs a Minidungeon without pasting the WorldEdit schematic")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupMinidungeonNoPasteCommand((Player) commandContext.getSender(), commandContext.get("minidungeonName"))));
+
+ // /em setup unminidungeon
+ manager.command(builder.literal("setup")
+ .literal("unminidungeon")
+ .argument(StringArgument.newBuilder("minidungeonName"), ArgumentDescription.of("minidungeon name"))
+ .meta(CommandMeta.DESCRIPTION, "Uninstalls a Minidungeon")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupUnminidungeonCommand((Player) commandContext.getSender(), commandContext.get("minidungeonName"))));
+
+ // /em setup unminidungeonNoPaste
+ manager.command(builder.literal("setup")
+ .literal("unminidungeonNoPaste")
+ .argument(StringArgument.newBuilder("minidungeonName"), ArgumentDescription.of("minidungeon name"))
+ .literal("noPaste")
+ .meta(CommandMeta.DESCRIPTION, "Uninstalls a Minidungeon without undoing a WorldEdit paste.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupUnminidungeonNoPasteCommand((Player) commandContext.getSender(), commandContext.get("minidungeonName"))));
+
+ // /em setup area
+ manager.command(builder.literal("setup")
+ .literal("area")
+ .argument(StringArgument.newBuilder("areaName"), ArgumentDescription.of("WorldGuard region name"))
+ .meta(CommandMeta.DESCRIPTION, "Protects an area using WorldGuard, used for Minidungeons and the Adventurer's World Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SetupHandler.setupAreaCommand((Player) commandContext.getSender(), commandContext.get("areaName"))));
+
+ ArrayList powers = new ArrayList<>();
+ for (ElitePower elitePower : ElitePower.getElitePowers())
+ powers.add(elitePower.getFileName());
+ powers.add("custom");
+
+ // /em spawnelite
+ manager.command(builder.literal("spawnelite")
+ .argument(EnumArgument.newBuilder(EntityType.class, "entityType"),
+ ArgumentDescription.of("Minecraft Entity Type, must be a valid type for an Elite"))
+ .argument(IntegerArgument.newBuilder("eliteLevel"), ArgumentDescription.of("Elite Mob level"))
+ .argument(StringArrayArgument.optional("powers", ((commandContext, lastString) -> powers)),
+ ArgumentDescription.of("List of powers"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an Elite based on the entity type.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnEliteEntityTypeCommand(
+ (Player) commandContext.getSender(),
+ commandContext.get("entityType"),
+ commandContext.get("eliteLevel"),
+ commandContext.getOrDefault("powers", new String[0]))));
+
+ // /em spawnlocationelite
+ manager.command(builder.literal("spawnlocationelite")
+ .argument(EnumArgument.newBuilder(EntityType.class, "entityType"),
+ ArgumentDescription.of("Minecraft Entity Type, must be a valid type for an Elite"))
+ .argument(StringArgument.newBuilder("worldName"), ArgumentDescription.of("Name of the world"))
+ .argumentTriplet("coords",
+ TypeToken.get(Vector.class),
+ Triplet.of("x", "y", "z"),
+ Triplet.of(Integer.class, Integer.class, Integer.class),
+ (sender, triplet) -> new Vector(triplet.getFirst(), triplet.getSecond(), triplet.getThird()),
+ ArgumentDescription.of("Coordinates"))
+ .argument(IntegerArgument.newBuilder("eliteLevel"), ArgumentDescription.of("Elite Mob level"))
+ .argument(StringArrayArgument.optional("powers", ((commandContext, lastString) -> powers)),
+ ArgumentDescription.of("List of powers"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an Elite based on the entity type and location.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnEliteEntityTypeCommand(
+ commandContext.getSender(),
+ commandContext.get("entityType"),
+ commandContext.get("worldName"),
+ commandContext.get("coords"),
+ commandContext.get("eliteLevel"),
+ commandContext.get("powers"))));
+
+ ArrayList customBosses = new ArrayList<>(CustomBossesConfig.getCustomBosses().keySet());
+ ArrayList regionalBosses = new ArrayList<>(CustomBossesConfigFields.getRegionalElites().keySet());
+
+ // /em spawncustom
+ manager.command(builder.literal("spawncustom", "spawncustomboss")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an Elite based on the entity type.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnCustomBossCommand(
+ (Player) commandContext.getSender(),
+ commandContext.get("fileName"))));
+
+ // /em spawncustomlevel
+ manager.command(builder.literal("spawncustomlevel", "spawncustombosslevel")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .argument(IntegerArgument.newBuilder("eliteLevel"), ArgumentDescription.of("Elite Mob level"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns a Custom Boss at a specific level.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnCustomBossCommand(
+ (Player) commandContext.getSender(),
+ commandContext.get("fileName"),
+ commandContext.get("eliteLevel"))));
+
+ // /em spawnlocationcustom
+ manager.command(builder.literal("spawnlocationcustom", "spawnlocationcustomboss")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .argument(StringArgument.newBuilder("worldName"), ArgumentDescription.of("Name of the world"))
+ .argumentTriplet("coords",
+ TypeToken.get(Vector.class),
+ Triplet.of("x", "y", "z"),
+ Triplet.of(Integer.class, Integer.class, Integer.class),
+ (sender, triplet) -> new Vector(triplet.getFirst(), triplet.getSecond(), triplet.getThird()),
+ ArgumentDescription.of("Coordinates"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an Elite based on the entity type and location.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnCustomBossCommand(
+ commandContext.getSender(),
+ commandContext.get("fileName"),
+ commandContext.get("worldName"),
+ commandContext.get("coords"))));
+
+ // /em spawnlocationcustomlevel
+ manager.command(builder.literal("spawnlocationcustomlevel", "spawnlocationcustombosslevel")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .argument(IntegerArgument.newBuilder("eliteLevel"), ArgumentDescription.of("Elite Mob level"))
+ .argument(StringArgument.newBuilder("worldName"), ArgumentDescription.of("Name of the world"))
+ .argumentTriplet("coords",
+ TypeToken.get(Vector.class),
+ Triplet.of("x", "y", "z"),
+ Triplet.of(Integer.class, Integer.class, Integer.class),
+ (sender, triplet) -> new Vector(triplet.getFirst(), triplet.getSecond(), triplet.getThird()),
+ ArgumentDescription.of("Coordinates"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an Elite based on the entity type and location.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnCustomBossCommand(
+ commandContext.getSender(),
+ commandContext.get("fileName"),
+ commandContext.get("worldName"),
+ commandContext.get("coords"),
+ commandContext.get("eliteLevel"))));
+
+ // /em spawnsuper
+ manager.command(builder.literal("spawnsuper", "spawnsupermob")
+ .argument(EnumArgument.newBuilder(EntityType.class, "entityType"),
+ ArgumentDescription.of("Minecraft Entity Type, must be a valid type for a Super Mob"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns a Super Mob based on the entity type.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SpawnCommand.spawnSuperMobCommand(
+ (Player) commandContext.getSender(),
+ commandContext.get("entityType"))));
+
+ // /em addSpawnLocation
+ manager.command(builder.literal("addSpawnLocation", "asp")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> regionalBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a spawn location to a Regional Boss.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CustomBossCommandHandler.addSpawnLocation(
+ commandContext.get("fileName"), (Player) commandContext.getSender())));
+
+ List treasureChestFilenames = new ArrayList<>(CustomTreasureChestsConfig.getCustomTreasureChestConfigFields().keySet());
+
+ // /em addTreasureChest
+ manager.command(builder.literal("addTreasureChest", "atc")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> treasureChestFilenames)),
+ ArgumentDescription.of("Treasure Chest configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a location to a Treasure Chest.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CustomTreasureChestsConfig.addTreasureChestEntry(
+ (Player) commandContext.getSender(), commandContext.get("fileName"))));
+
+ ArrayList minidungeonFileNames = new ArrayList<>(Minidungeon.getMinidungeons().keySet());
+
+ // /em addRelativeSpawnLocation
+ manager.command(builder.literal("addRelativeSpawnLocation", "arsp")
+ .argument(StringArgument.newBuilder("bossFileName").withSuggestionsProvider(((objectCommandContext, s) -> regionalBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .argument(StringArgument.newBuilder("minidungeonFileName").withSuggestionsProvider(((objectCommandContext, s) -> minidungeonFileNames)),
+ ArgumentDescription.of("Minidungeon configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a spawn location to a Regional Boss.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CustomBossCommandHandler.addRelativeSpawnLocation(
+ (Player) commandContext.getSender(), commandContext.get("bossFileName"), commandContext.get("minidungeonFileName"))));
+
+ // /em addRelativeTreasureChest
+ manager.command(builder.literal("addRelativeTreasureChest", "artc")
+ .argument(StringArgument.newBuilder("treasureChestFilename").withSuggestionsProvider(((objectCommandContext, s) -> treasureChestFilenames)),
+ ArgumentDescription.of("Treasure Chest configuration file name"))
+ .argument(StringArgument.newBuilder("minidungeonFileName").withSuggestionsProvider(((objectCommandContext, s) -> minidungeonFileNames)),
+ ArgumentDescription.of("Minidungeon configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a spawn location to a Regional Boss.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> TreasureChestCommands.addRelativeTreasureChest(
+ (Player) commandContext.getSender(), commandContext.get("treasureChestFilename"), commandContext.get("minidungeonFileName"))));
+
+ // /em setLeashRadius
+ manager.command(builder.literal("setLeashRadius")
+ .argument(StringArgument.newBuilder("fileName").withSuggestionsProvider(((objectCommandContext, s) -> regionalBosses)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .argument(DoubleArgument.newBuilder("radius"), ArgumentDescription.of("Radius of the Regional Boss leash"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a spawn location to a Regional Boss.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CustomBossCommandHandler.setLeashRadius(
+ commandContext.get("fileName"), commandContext.getSender(), commandContext.get("radius"))));
+
+ // /em remove
+ manager.command(builder.literal("remove", "r")
+ .meta(CommandMeta.DESCRIPTION, "Permanently removes an Elite Mob entity. Elite/Regional/Super/NPCs all work.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> RemoveCommand.remove((Player) commandContext.getSender())));
+
+
+ // /em debug
+ manager.command(builder.literal("debug", "d")
+ .argument(StringArgument.newBuilder("argument").withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList((Collection extends String>) regionalBosses.clone());
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })),
+ ArgumentDescription.of("Player name or regional boss file name"))
+ .meta(CommandMeta.DESCRIPTION, "Opens a debug screen for players or regional bosses.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> DebugScreen.open((Player) commandContext.getSender(), commandContext.get("argument"))));
+
+ ArrayList events = new ArrayList<>();
+ TimedEvent.getBlueprintEvents().stream().forEach(event -> events.add(event.getCustomEventsConfigFields().getFilename()));
+
+ // /em event
+ manager.command(builder.literal("event")
+ .argument(StringArgument.newBuilder("events").withSuggestionsProvider(((objectCommandContext, s) -> events)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Opens a debug screen for players or regional bosses.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> EventCommand.trigger(commandContext.getSender(), commandContext.get("events"))));
+
+ ArrayList npcs = new ArrayList<>(NPCsConfig.npcEntities.keySet());
+
+ // /em spawnnpc
+ manager.command(builder.literal("spawnnpc")
+ .argument(StringArgument.newBuilder("npcFileName").withSuggestionsProvider(((objectCommandContext, s) -> npcs)),
+ ArgumentDescription.of("Custom Boss configuration file name"))
+ .meta(CommandMeta.DESCRIPTION, "Spawns an NPC")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> NPCCommands.set((Player) commandContext.getSender(), commandContext.get("npcFileName"))));
+
+ // /em stats
+ manager.command(builder.literal("stats")
+ .meta(CommandMeta.DESCRIPTION, "Gets the stats for the currently active EliteMobs entities and players.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.stats")
+ .handler(commandContext -> StatsCommand.statsHandler(commandContext.getSender())));
+
+ // /em getloot
+ manager.command(builder.literal("getloot")
+ .meta(CommandMeta.DESCRIPTION, "Opens a menu where you can get any Custom Loot")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> new GetLootMenu((Player) commandContext.getSender())));
+
+ ArrayList customItems = new ArrayList<>(CustomItem.getCustomItems().keySet());
+
+ // /em getloot
+ manager.command(builder.literal("getloot")
+ .argument(StringArgument.newBuilder("customItem").withSuggestionsProvider(((objectCommandContext, s) -> customItems)),
+ ArgumentDescription.of("File name of the custom item"))
+ .meta(CommandMeta.DESCRIPTION, "Gets a specific custom item")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> LootCommand.get((Player) commandContext.getSender(), commandContext.get("customItem"))));
+
+ // /em giveloot
+ manager.command(builder.literal("give")
+ .argument(StringArgument.newBuilder("customItem").withSuggestionsProvider(((objectCommandContext, s) -> customItems)),
+ ArgumentDescription.of("File name of the custom item"))
+ .argument(StringArgument.newBuilder("player").withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })),
+ ArgumentDescription.of("Name of the player that will get the custom item"))
+ .meta(CommandMeta.DESCRIPTION, "Gives a specific custom item to a player.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> LootCommand.give(commandContext.getSender(),
+ commandContext.get("player"),
+ commandContext.get("customItem"))));
+
+ // /em simloot
+ manager.command(builder.literal("simloot")
+ .argument(IntegerArgument.newBuilder("level"),
+ ArgumentDescription.of("Level of Elite Mob to simulate"))
+ .meta(CommandMeta.DESCRIPTION, "Simulates drops from an Elite Mob from the set tier")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SimLootCommand.run((Player) commandContext.getSender(), commandContext.get("level"))));
+
+ // /em simloot
+ manager.command(builder.literal("simloot")
+ .argument(IntegerArgument.newBuilder("level"),
+ ArgumentDescription.of("Level of Elite Mob to simulate"))
+ .argument(IntegerArgument.newBuilder("times"),
+ ArgumentDescription.of("Number of times that the simulation will run"))
+ .meta(CommandMeta.DESCRIPTION, "Simulates drops from an Elite Mob from the set tier a set amount of times")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SimLootCommand.runMultipleTimes(
+ (Player) commandContext.getSender(),
+ commandContext.get("level"),
+ commandContext.get("times"))));
+
+ // /em simlootother
+ manager.command(builder.literal("simlootother")
+ .argument(IntegerArgument.newBuilder("level"),
+ ArgumentDescription.of("Level of Elite Mob to simulate"))
+ .meta(CommandMeta.DESCRIPTION, "Simulates drops from an Elite Mob from the set tier")
+ .argument(StringArgument.newBuilder("player").withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })),
+ ArgumentDescription.of("Name of the player that will get the custom item"))
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SimLootCommand.run(commandContext.getSender(), commandContext.get("level"), commandContext.get("player"))));
+
+ // /em simlootothermultiple
+ manager.command(builder.literal("simlootothermultiple")
+ .argument(IntegerArgument.newBuilder("level"),
+ ArgumentDescription.of("Level of Elite Mob to simulate"))
+ .argument(IntegerArgument.newBuilder("times"),
+ ArgumentDescription.of("Number of times that the simulation will run"))
+ .meta(CommandMeta.DESCRIPTION, "Simulates drops from an Elite Mob from the set tier a set amount of times")
+ .argument(StringArgument.newBuilder("target").withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })),
+ ArgumentDescription.of("Name of the player that will get the custom item"))
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> SimLootCommand.runMultipleTimes(
+ commandContext.getSender(),
+ commandContext.get("level"),
+ commandContext.get("times"),
+ commandContext.get("target"))));
+
+ // /em version
+ manager.command(builder.literal("version")
+ .meta(CommandMeta.DESCRIPTION, "Gets the version of the plugin")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.version")
+ .handler(commandContext -> VersionCommand.getVersion(commandContext.getSender())));
+
+ // /em reload
+ manager.command(builder.literal("reload")
+ .meta(CommandMeta.DESCRIPTION, "Reloads the plugin. Works almost every time.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> ReloadCommand.reload(commandContext.getSender())));
+
+ // /em killaggressive
+ manager.command(builder.literal("killaggressive")
+ .meta(CommandMeta.DESCRIPTION, "Kills all aggressive Elite Mobs.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.killAggressiveMobs(commandContext.getSender())));
+
+ // /em killaggressive
+ manager.command(builder.literal("killaggressive")
+ .argument(IntegerArgument.newBuilder("radius"),
+ ArgumentDescription.of("Distance to kill aggressive elite mobs in"))
+ .meta(CommandMeta.DESCRIPTION, "Kills all aggressive Elite Mobs in a radius.")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.radiusKillAggressiveMobs((Player) commandContext.getSender(), commandContext.get("radius"))));
+
+ // /em killpassive
+ manager.command(builder.literal("killpassive")
+ .meta(CommandMeta.DESCRIPTION, "Kills all passive Super Mobs")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.killPassiveMobs(commandContext.getSender())));
+
+ // /em killpassive
+ manager.command(builder.literal("killpassive")
+ .argument(IntegerArgument.newBuilder("radius"),
+ ArgumentDescription.of("Distance to kill aggressive elite mobs in"))
+ .meta(CommandMeta.DESCRIPTION, "Kills all passive Super Mobs in a radius")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.radiusKillPassiveMobs((Player) commandContext.getSender(), commandContext.get("radius"))));
+
+
+ // /em killtype
+ manager.command(builder.literal("killtype")
+ .argument(EnumArgument.newBuilder(EntityType.class, "entityType"),
+ ArgumentDescription.of("Minecraft Entity Type to kill"))
+ .meta(CommandMeta.DESCRIPTION, "Kills all elites of a specific type")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.killEntityType(commandContext.getSender(), commandContext.get("entityType"))));
+
+ // /em killtype
+ manager.command(builder.literal("killtype")
+ .argument(EnumArgument.newBuilder(EntityType.class, "entityType"),
+ ArgumentDescription.of("Minecraft Entity Type to kill"))
+ .argument(IntegerArgument.newBuilder("radius"),
+ ArgumentDescription.of("Distance to kill aggressive elite mobs in"))
+ .meta(CommandMeta.DESCRIPTION, "Kills all elites of a specific type in a radius")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> KillHandler.radiusKillSpecificMobs((Player) commandContext.getSender(),
+ commandContext.get("entityType"),
+ commandContext.get("radius"))));
+
+ // /em gettier
+ manager.command(builder.literal("gettier")
+ .argument(IntegerArgument.newBuilder("tier"),
+ ArgumentDescription.of("Tier of the item to get"))
+ .meta(CommandMeta.DESCRIPTION, "Gets debug items for testing purposes")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> GetTierCommand.get((Player) commandContext.getSender(), commandContext.get("tier"))));
+
+
+ CommandArgument onlinePlayers = StringArgument.newBuilder("onlinePlayer")
+ .withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })).build();
+
+ // /em money add
+ manager.command(builder.literal("money")
+ .literal("add")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .argument(IntegerArgument.newBuilder("amount"), ArgumentDescription.of("Amount of money to add"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a set amount of money to a player")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CurrencyCommandsHandler.addCommand(commandContext.getSender(),
+ commandContext.get("onlinePlayer"),
+ commandContext.get("amount"))));
+
+ // /em money addall
+ manager.command(builder.literal("money")
+ .literal("addall")
+ .argument(IntegerArgument.newBuilder("amount"), ArgumentDescription.of("Amount of money to add"))
+ .meta(CommandMeta.DESCRIPTION, "Adds a set amount of money to all online players")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CurrencyCommandsHandler.addAllCommand(commandContext.getSender(),
+ commandContext.get("amount"))));
+
+ // /em money remove
+ manager.command(builder.literal("money")
+ .literal("remove")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .argument(IntegerArgument.newBuilder("amount"), ArgumentDescription.of("Amount of money to add"))
+ .meta(CommandMeta.DESCRIPTION, "Removes a set amount of money from a player")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CurrencyCommandsHandler.subtractCommand(commandContext.getSender(),
+ commandContext.get("onlinePlayer"),
+ commandContext.get("amount"))));
+
+ // /em money set
+ manager.command(builder.literal("money")
+ .literal("set")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .argument(DoubleArgument.newBuilder("amount"), ArgumentDescription.of("Amount to be set"))
+ .meta(CommandMeta.DESCRIPTION, "Sets the total currency amount of a player")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> CurrencyCommandsHandler.setCommand(commandContext.getSender(),
+ commandContext.get("onlinePlayer"),
+ commandContext.get("amount"))));
+
+ // /em setrank
+ manager.command(builder.literal("setrank")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .argument(IntegerArgument.newBuilder("prestigeRank"), ArgumentDescription.of("Prestige rank, 0-10"))
+ .argument(IntegerArgument.newBuilder("guildRank"), ArgumentDescription.of("Guild rank, 0-20"))
+ .meta(CommandMeta.DESCRIPTION, "Sets the guild rank of a player.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> GuildRankCommands.setGuildRank(commandContext.getSender(),
+ commandContext.get("onlinePlayer"),
+ commandContext.get("prestigeRank"),
+ commandContext.get("guildRank"))));
+
+ // /em discord
+ manager.command(builder.literal("discord")
+ .meta(CommandMeta.DESCRIPTION, "Gets the link for the support Discord server.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> commandContext.getSender().sendMessage(
+ ChatColorConverter.convert("&8[EliteMobs] &6Discord room for support & downloads: &9" + DiscordLinks.mainLink))));
+
+ // /em discord
+ manager.command(builder.literal("discord")
+ .argument(StringArgument.newBuilder("message").greedy().build(),
+ ArgumentDescription.of("Message to be sent to Discord"))
+ .meta(CommandMeta.DESCRIPTION, "Posts a debug message on Discord if DiscordSRV is configured correctly.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .handler(commandContext -> {
+ new DiscordSRVAnnouncement(commandContext.get("message"));
+ commandContext.getSender().sendMessage(ChatColorConverter.convert("&8[EliteMobs] &aAttempted to send a message to Discord!"));
+ }));
+
+ // /em forceunbind
+ manager.command(builder.literal("forceunbind")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Unbinds a held soulbound item.")
+ .handler(commandContext -> {
+ ItemStack itemStack = ((Player) commandContext.getSender()).getInventory().getItemInMainHand();
+ if (ItemTagger.isEliteItem(itemStack))
+ SoulbindEnchantment.removeEnchantment(itemStack);
+ }));
+
+ // /em relativecoords
+ manager.command(builder.literal("relativecoords")
+ .argument(StringArgument.newBuilder("minidungeonFileName").withSuggestionsProvider(((objectCommandContext, s) -> minidungeonFileNames)),
+ ArgumentDescription.of("Minidungeon configuration file name"))
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Gets the relative coordinated to an installed dungeon.")
+ .handler(commandContext -> RelativeCoordinatesCommand.get((Player) commandContext.getSender(), commandContext.get("minidungeonFileName"))));
+
+ // /em wallet
+ manager.command(builder.literal("wallet")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .senderType(CommandSender.class)
+ .permission("elitemobs.currency.check.others")
+ .meta(CommandMeta.DESCRIPTION, "Checks the currency of a specific player.")
+ .handler(commandContext -> CurrencyCommandsHandler.checkCommand(commandContext.getSender(), commandContext.get("onlinePlayer"))));
+
+ // /em fireball
+ manager.command(builder.literal("fireball")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Fires a test Elite Fireball for explosion protection and regeneration testing purposes.")
+ .handler(commandContext -> testFireball((Player) commandContext.getSender())));
+
+ List blockTransitionPhases = new ArrayList<>(Arrays.asList("ON_SPAWN", "ON_REMOVE"));
+
+ // /em registerblocks
+ manager.command(builder.literal("registerblocks")
+ .senderType(Player.class)
+ .argument(StringArgument.newBuilder("regionalBoss").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Regional Boss configuration file name"))
+ .argument(StringArgument.newBuilder("blockTransitionPhase").withSuggestionsProvider(((objectCommandContext, s) -> blockTransitionPhases)),
+ ArgumentDescription.of("Block transition phase"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Registers transitive blocks for use by regional bosses.")
+ .handler(commandContext -> TransitiveBlockCommand.processCommand((Player) commandContext.getSender(),
+ commandContext.get("regionalBoss"), commandContext.get("blockTransitionPhase"), false)));
+
+ // /em registerblocksedit
+ manager.command(builder.literal("registerblocksedit")
+ .senderType(Player.class)
+ .argument(StringArgument.newBuilder("regionalBoss").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Regional Boss configuration file name"))
+ .argument(StringArgument.newBuilder("blockTransitionPhase").withSuggestionsProvider(((objectCommandContext, s) -> blockTransitionPhases)),
+ ArgumentDescription.of("Block transition phase"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Registers transitive blocks for use by regional bosses.")
+ .handler(commandContext -> TransitiveBlockCommand.processCommand((Player) commandContext.getSender(),
+ commandContext.get("regionalBoss"), commandContext.get("blockTransitionPhase"), true)));
+
+ // /em registerblocksarea
+ manager.command(builder.literal("registerblocksarea")
+ .senderType(Player.class)
+ .argument(StringArgument.newBuilder("regionalBoss").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Regional Boss configuration file name"))
+ .argument(StringArgument.newBuilder("blockTransitionPhase").withSuggestionsProvider(((objectCommandContext, s) -> blockTransitionPhases)),
+ ArgumentDescription.of("Block transition phase"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Registers large transitive blocks areas for use by regional bosses.")
+ .handler(commandContext -> TransitiveBlockCommand.processCommand((Player) commandContext.getSender(),
+ commandContext.get("regionalBoss"), commandContext.get("blockTransitionPhase"), false, true)));
+
+ // /em registerblocksareaedit
+ manager.command(builder.literal("registerblocksareaedit")
+ .senderType(Player.class)
+ .argument(StringArgument.newBuilder("regionalBoss").withSuggestionsProvider(((objectCommandContext, s) -> customBosses)),
+ ArgumentDescription.of("Regional Boss configuration file name"))
+ .argument(StringArgument.newBuilder("blockTransitionPhase").withSuggestionsProvider(((objectCommandContext, s) -> blockTransitionPhases)),
+ ArgumentDescription.of("Block transition phase"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Edits large transitive blocks areas for use by regional bosses.")
+ .handler(commandContext -> TransitiveBlockCommand.processCommand((Player) commandContext.getSender(),
+ commandContext.get("regionalBoss"), commandContext.get("blockTransitionPhase"), true, true)));
+
+ // /em cancelblocks
+ manager.command(builder.literal("cancelblocks")
+ .senderType(Player.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Cancels transitive block registration for a player.")
+ .handler(commandContext -> TransitiveBlockCommand.processCommand((Player) commandContext.getSender())));
+
+ // /em debugmode
+ manager.command(builder.literal("debugmode")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Toggles debug messages off and on.")
+ .handler(commandContext -> DebugMessage.toggleDebugMode(commandContext.getSender())));
+
+ // /em trace
+ manager.command(builder.literal("trace")
+ .senderType(CommandSender.class)
+ .argument(StringArgument.newBuilder("uuid"),
+ ArgumentDescription.of("EliteMobs UUID of the Custom Boss"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Traces the life of a custom boss entity. Used by the debug menu.")
+ .handler(commandContext -> {
+ for (EliteEntity eliteEntity : EntityTracker.getEliteMobEntities().values())
+ if (eliteEntity.getEliteUUID().toString().equals(commandContext.get("uuid")))
+ if (eliteEntity instanceof CustomBossEntity) {
+ ((CustomBossEntity) eliteEntity).getBossTrace().postLog((Player) commandContext.getSender());
+ return;
+ }
+ }));
+
+ // /em debugtp
+ manager.command(builder.literal("debugtp")
+ .senderType(CommandSender.class)
+ .argument(StringArgument.newBuilder("uuid"),
+ ArgumentDescription.of("EliteMobs UUID of the Custom Boss"))
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Traces the life of a custom boss entity. Used by the debug menu.")
+ .handler(commandContext -> {
+ for (EliteEntity eliteEntity : EntityTracker.getEliteMobEntities().values())
+ if (eliteEntity.getEliteUUID().toString().equals(commandContext.get("uuid")))
+ if (eliteEntity instanceof CustomBossEntity) {
+ if (eliteEntity.getLocation() != null)
+ ((Player) commandContext.getSender()).teleport(eliteEntity.getLocation());
+ return;
+ }
+ }));
+
+ // /em generateresourcepack
+ manager.command(builder.literal("generateresourcepack")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Generates a resource pack for EliteMobs using ModelEngine")
+ .handler(commandContext -> ConfigurationExporter.createResourcePack(commandContext.getSender())));
+
+ // /em updateresourcepack
+ manager.command(builder.literal("updateresourcepack")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Updates the SHA1 texture pack code based on the zipped resource pack in the exports.")
+ .handler(commandContext -> ConfigurationExporter.overwriteSHA1(commandContext.getSender())));
+
+
+ // /em quest reset player
+ manager.command(builder.literal("quest")
+ .literal("reset")
+ .argument(StringArgument.newBuilder("player").withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })))
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Resets player quest progress.")
+ .handler(commandContext -> QuestCommand.resetQuests(commandContext.getSender(), commandContext.get("player"))));
+
+ // /em quest forcecomplete
+ manager.command(builder.literal("quest")
+ .literal("forcecomplete")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.*")
+ .meta(CommandMeta.DESCRIPTION, "Forces completion of all player quests.")
+ .handler(commandContext -> QuestCommand.completeQuest((Player) commandContext.getSender())));
+ }
+
+ private void testFireball(Player player) {
+ Fireball fireball = (Fireball) player.getWorld().spawnEntity(player.getLocation(), EntityType.FIREBALL);
+ fireball.setDirection(player.getLocation().getDirection().normalize());
+ fireball.setShooter(player);
+ fireball.setYield(3F);
+ EntityTracker.registerProjectileEntity(fireball);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/ArenaCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/ArenaCommands.java
new file mode 100644
index 000000000..9a1c4cd86
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/ArenaCommands.java
@@ -0,0 +1,11 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.menus.ArenaMenu;
+import org.bukkit.entity.Player;
+
+public class ArenaCommands {
+ public static void openArenaMenu(Player player, String arenaFilename) {
+ ArenaMenu arenaMenu = new ArenaMenu();
+ arenaMenu.constructArenaMenu(player, arenaFilename);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/CheckMaxItemTierCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/CheckMaxItemTierCommand.java
deleted file mode 100644
index faa16eb9b..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/CheckMaxItemTierCommand.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.ItemsDropSettingsConfig;
-import com.magmaguy.elitemobs.config.ItemsProceduralSettingsConfig;
-import com.magmaguy.elitemobs.config.MobCombatSettingsConfig;
-import org.bukkit.command.CommandSender;
-
-public class CheckMaxItemTierCommand {
-
- public static void checkMaxItemTier(CommandSender commandSender) {
-
- commandSender.sendMessage("The current maximum item tier is tier " + ConfigValues.itemsDropSettingsConfig.getString(ItemsDropSettingsConfig.MAXIMUM_LOOT_TIER));
- commandSender.sendMessage("The current maximum power enchantment is " + ConfigValues.itemsProceduralSettingsConfig.getString(ItemsProceduralSettingsConfig.ARROW_DAMAGE_MAX_LEVEL));
- commandSender.sendMessage("The current maximum sharpness enchantment is " + ConfigValues.itemsProceduralSettingsConfig.getString(ItemsProceduralSettingsConfig.DAMAGE_ALL_MAX_LEVEL));
- commandSender.sendMessage("The current maximum protection enchantment is " + ConfigValues.itemsProceduralSettingsConfig.getString(ItemsProceduralSettingsConfig.PROTECTION_ENVIRONMENTAL_MAX_LEVEL));
- commandSender.sendMessage("The current maximum natural mob level is " + ConfigValues.mobCombatSettingsConfig.getString(MobCombatSettingsConfig.NATURAL_ELITEMOB_LEVEL_CAP));
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/CheckTierCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/CheckTierCommand.java
deleted file mode 100644
index 18a6ca642..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/CheckTierCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.adventurersguild.GuildRank;
-import com.magmaguy.elitemobs.items.ItemTierFinder;
-import org.bukkit.entity.Player;
-
-public class CheckTierCommand {
-
- public static void checkTier(Player player) {
-
- double gearTier = ItemTierFinder.findPlayerTier(player);
- double guildTier = (GuildRank.getGuildRank(player.getUniqueId()) - 10) * 0.2;
-
- player.sendMessage("Your combat tier is " + gearTier);
- player.sendMessage("Your guild tier bonus is " + guildTier);
- player.sendMessage("Your threat tier is " + (gearTier + guildTier));
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/CommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/CommandHandler.java
index 941813756..e00922427 100644
--- a/src/main/java/com/magmaguy/elitemobs/commands/CommandHandler.java
+++ b/src/main/java/com/magmaguy/elitemobs/commands/CommandHandler.java
@@ -1,349 +1,144 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
+import cloud.commandframework.Command;
+import cloud.commandframework.CommandTree;
+import cloud.commandframework.arguments.standard.StringArgument;
+import cloud.commandframework.bukkit.BukkitCommandManager;
+import cloud.commandframework.execution.CommandExecutionCoordinator;
+import cloud.commandframework.meta.CommandMeta;
+import cloud.commandframework.minecraft.extras.MinecraftExceptionHandler;
+import cloud.commandframework.minecraft.extras.MinecraftHelp;
import com.magmaguy.elitemobs.MetadataHandler;
-import com.magmaguy.elitemobs.adventurersguild.AdventurersGuildGUI;
-import com.magmaguy.elitemobs.commands.shops.CustomShopHandler;
-import com.magmaguy.elitemobs.commands.shops.ShopHandler;
-import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
-import com.magmaguy.elitemobs.config.ConfigValues;
+import com.magmaguy.elitemobs.commands.guild.AdventurersGuildCommand;
import com.magmaguy.elitemobs.config.DefaultConfig;
-import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
+import com.magmaguy.elitemobs.items.ShareItem;
+import com.magmaguy.elitemobs.playerdata.statusscreen.PlayerStatusScreen;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import net.kyori.adventure.platform.bukkit.BukkitAudiences;
+import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
+import java.lang.reflect.Method;
+import java.util.function.Function;
+
+import static net.kyori.adventure.text.Component.text;
+
/**
* Created by MagmaGuy on 21/01/2017.
*/
-public class CommandHandler implements CommandExecutor {
-
- private final static String STATS = "elitemobs.stats";
- private final static String GETLOOT = "elitemobs.getloot";
- private final static String SIMLOOT = "elitemobs.simloot";
- public final static String RELOAD_CONFIGS = "elitemobs.reload";
- private final static String RELOAD_LOOT = "elitemobs.reload.loot";
- private final static String GIVELOOT = "elitemobs.giveloot";
- private final static String SPAWNMOB = "elitemobs.spawnmob";
- private final static String SPAWN_BOSS_MOB = "elitemobs.spawnbossmob";
- public final static String KILLALL_AGGRESSIVEELITES = "elitemobs.killall.aggressiveelites";
- public final static String KILLALL_PASSIVEELITES = "elitemobs.killall.passiveelites";
- public final static String KILLALL_SPECIFICENTITY = "elitemobs.killall.specificentity";
- private final static String SHOP = "elitemobs.shop";
- private final static String CUSTOMSHOP = "elitemobs.customshop";
- private final static String CURRENCY_PAY = "elitemobs.currency.pay";
- private final static String CURRENCY_ADD = "elitemobs.currency.add";
- private final static String CURRENCY_SUBTRACT = "elitemobs.currency.subtract";
- private final static String CURRENCY_SET = "elitemobs.currency.set";
- private final static String CURRENCY_CHECK = "elitemobs.currency.check";
- private final static String CURRENCY_WALLET = "elitemobs.currency.wallet";
- private final static String CURRENCY_COINTOP = "elitemobs.currency.cointop";
- private final static String VERSION = "elitemobs.version";
- public final static String EVENT_LAUNCH_SMALLTREASUREGOBLIN = "elitemobs.events.smalltreasuregoblin";
- public final static String EVENT_LAUNCH_DEADMOON = "elitemobs.events.smalltreasuregoblin";
- private final static String CHECK_TIER = "elitemobs.checktier";
- private final static String SET_MAX_TIER = "elitemobs.config.setmaxtier";
- private final static String GET_TIER = "elitemobs.gettier";
- private final static String CHECK_MAX_TIER = "elitemobs.checkmaxtier";
- private final static String ADVENTURERS_GUILD = "elitemobs.adventurersguild";
-
- @Override
- public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args) {
-
- switch (label) {
- case "ag":
- case "adventurersguild":
- case "adventurerguild":
- if (userPermCheck(ADVENTURERS_GUILD, commandSender) && ConfigValues.adventurersGuildConfig.getBoolean(AdventurersGuildConfig.ENABLE_ADVENTURERS_GUILD))
- AdventurersGuildGUI.mainMenu((Player) commandSender);
- return true;
- }
-
- if (args.length == 0) {
- validCommands(commandSender);
- return true;
+public class CommandHandler {
+
+ private BukkitCommandManager manager;
+ //private CommandConfirmationManager paymentConfirmationManager;
+ private MinecraftHelp minecraftHelp;
+ private BukkitAudiences bukkitAudiences;
+
+ /*
+ Commands powered by Cloud
+ */
+
+ public CommandHandler() {
+ Function commandExecutionCoordinator = null;
+ try {
+ Class> c = Class.forName("cloud.commandframework.execution.CommandExecutionCoordinator");
+ Method method = c.getDeclaredMethod("simpleCoordinator");
+ commandExecutionCoordinator = (Function) method.invoke(Function.class);
+ } catch (Exception e) {
+ e.printStackTrace();
}
-
- args[0] = args[0].toLowerCase();
-
- switch (args[0]) {
- case "spawn":
- case "spawnmob":
- if (permCheck(SPAWNMOB, commandSender))
- SpawnMobCommandHandler.spawnMob(commandSender, args);
- return true;
- case "ag":
- case "adventurersguild":
- case "adventurerguild":
- if (userPermCheck(ADVENTURERS_GUILD, commandSender))
- AdventurersGuildGUI.mainMenu((Player) commandSender);
- return true;
- case "stats":
- if (permCheck(STATS, commandSender))
- StatsCommandHandler.statsHandler(commandSender);
- return true;
- case "getloot":
- case "gl":
- if (userPermCheck(GETLOOT, commandSender) && args.length == 1) {
- LootGUI lootGUI = new LootGUI();
- lootGUI.lootGUI((Player) commandSender);
- } else {
- if (GetLootCommandHandler.getLoot(((Player) commandSender), args[1]))
- return true;
- else
- ((Player) commandSender).sendTitle("", "Could not find that item name.");
- }
- return true;
- case "shop":
- case "store":
- if (userPermCheck(SHOP, commandSender)) {
- ShopHandler shopHandler = new ShopHandler();
- shopHandler.initializeShop((Player) commandSender);
- }
- return true;
- case "customshop":
- case "cshop":
- case "customstore":
- case "cstore":
- if (userPermCheck(CUSTOMSHOP, commandSender)) {
- CustomShopHandler customShopHandler = new CustomShopHandler();
- customShopHandler.initializeShop((Player) commandSender);
- }
- return true;
- case "wallet":
- case "bal":
- case "balance":
- case "currency":
- case "money":
- case "$":
- if (userPermCheck(CURRENCY_WALLET, commandSender))
- CurrencyCommandsHandler.walletCommand(commandSender, args);
- return true;
- case "cointop":
- case "baltop":
- case "cashtop":
- case "currencytop":
- case "$top":
- if (userPermCheck(CURRENCY_COINTOP, commandSender))
- CurrencyCommandsHandler.coinTop(commandSender);
- return true;
- case "version":
- if (permCheck(VERSION, commandSender))
- VersionHandler.versionCommand(commandSender, args);
- return true;
- case "checktier":
- case "tiercheck":
- case "tier":
- if (permCheck(CHECK_TIER, commandSender))
- CheckTierCommand.checkTier(((Player) commandSender));
- return true;
- case "checkmaxtier":
- case "maxtier":
- if (permCheck(CHECK_MAX_TIER, commandSender))
- CheckMaxItemTierCommand.checkMaxItemTier(commandSender);
- return true;
- case "reload":
- case "restart":
- if (permCheck(RELOAD_CONFIGS, commandSender))
- ReloadHandler.reloadCommand(commandSender, args);
- return true;
- case "killall":
- case "kill":
- KillHandler.killCommand(commandSender, args);
- return true;
- case "simloot":
- case "simulateloot":
- case "simdrop":
- case "simulatedrop":
- if (userPermCheck(SIMLOOT, commandSender))
- SimLootHandler.simLoot((Player) commandSender, Integer.parseInt(args[1]));
- return true;
- case "check":
- case "checkcurrency":
- case "checkbal":
- case "checkbalance":
- case "check$":
- if (permCheck(CURRENCY_CHECK, commandSender))
- CurrencyCommandsHandler.checkCommand(commandSender, args);
- return true;
- case "event":
- case "launchevent":
- case "startevent":
- case "triggerevent":
- TriggerEventHandler.triggerEventCommand(commandSender, args);
- return true;
- case "spawnbossmob":
- case "spawnboss":
- if (userPermCheck(SPAWNMOB, commandSender))
- SpawnMobCommandHandler.spawnBossMob((Player) commandSender, args);
- return true;
- case "gettier":
- case "spawntier":
- if (userPermCheck(GET_TIER, commandSender))
- TierSetSpawner.spawnTierItem(Integer.parseInt(args[1]), (Player) commandSender);
- return true;
- case "setmaxtier":
- if (permCheck(SET_MAX_TIER, commandSender))
- SetMaxItemTierCommand.setMaxItemTier(Double.parseDouble(args[1]), commandSender);
- return true;
- case "giveloot":
- if (permCheck(GIVELOOT, commandSender))
- GiveLootHandler.giveLootCommand(commandSender, args);
- return true;
- case "pay":
- if (userPermCheck(CURRENCY_PAY, commandSender))
- CurrencyCommandsHandler.payCommand((Player) commandSender, args);
- return true;
- case "add":
- if (permCheck(CURRENCY_ADD, commandSender))
- CurrencyCommandsHandler.addCommand(commandSender, args);
- return true;
- case ("subtract"):
- if (permCheck(CURRENCY_SUBTRACT, commandSender))
- CurrencyCommandsHandler.subtractCommand(commandSender, args);
- return true;
- case ("set"):
- if (permCheck(CURRENCY_SET, commandSender))
- CurrencyCommandsHandler.setCommand(commandSender, args);
- return true;
- default:
- validCommands(commandSender);
- return true;
-
+ try {
+ manager = new BukkitCommandManager(
+ /* Owning plugin */ MetadataHandler.PLUGIN,
+ /* Coordinator function */ commandExecutionCoordinator,
+ /* Command Sender -> C */ Function.identity(),
+ /* C -> Command Sender */ Function.identity()
+ );
+ } catch (final Exception e) {
+ new WarningMessage("Failed to initialize the command manager");
+ /* Disable the plugin */
+ MetadataHandler.PLUGIN.getServer().getPluginManager().disablePlugin(MetadataHandler.PLUGIN);
+ return;
}
+ //try {
+ // manager.registerBrigadier();
+ //} catch (final Exception e) {
+ // new WarningMessage("Failed to initialize Brigadier support: " + e.getMessage());
+ //}
+
+ // Create a BukkitAudiences instance (adventure) in order to use the minecraft-extras help system
+ bukkitAudiences = BukkitAudiences.create(MetadataHandler.PLUGIN);
+
+ minecraftHelp = new MinecraftHelp(
+ "/elitemobs help",
+ bukkitAudiences::sender,
+ manager
+ );
+
+ // Override the default exception handlers
+ new MinecraftExceptionHandler()
+ .withInvalidSyntaxHandler()
+ .withInvalidSenderHandler()
+ .withNoPermissionHandler()
+ .withArgumentParsingHandler()
+ .withCommandExecutionHandler()
+ .withDecorator(
+ component -> text()
+ .append(text("[", NamedTextColor.DARK_GRAY))
+ .append(text("Example", NamedTextColor.GOLD))
+ .append(text("] ", NamedTextColor.DARK_GRAY))
+ .append(component).build()
+ ).apply(manager, bukkitAudiences::sender);
+
+ constructCommands();
}
- public static boolean permCheck(String permission, CommandSender commandSender) {
-
- if (commandSender.hasPermission(permission)) return true;
-
- if (commandSender instanceof Player &&
- Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS).getConfig().getBoolean(DefaultConfig.ENABLE_PERMISSION_TITLES)) {
-
- Player player = (Player) commandSender;
-
- player.sendTitle("I'm afraid I can't let you do that, " + player.getDisplayName() + ".",
- "You need the following permission: " + permission);
-
- } else {
-
- commandSender.sendMessage("[EliteMobs] You may not run this command.");
- commandSender.sendMessage("[EliteMobs] You don't have the permission " + permission);
-
- }
-
- return false;
+ public void constructCommands() {
+
+ // /ag
+ final Command.Builder agBuilder = manager.commandBuilder("adventurersguild", "ag");
+ manager.command(agBuilder.meta(CommandMeta.DESCRIPTION, "Teleports players to the Adventurers' Guild Hub")
+ .senderType(Player.class)
+ //permission is dealt inside of the command
+ .handler(commandContext -> {
+ if (DefaultConfig.isEmLeadsToStatusMenu())
+ AdventurersGuildCommand.adventurersGuildCommand((Player) commandContext.getSender());
+ }));
+
+ // /shareitem
+ final Command.Builder shareItemBuilder = manager.commandBuilder("shareitem");
+ manager.command(shareItemBuilder.meta(CommandMeta.DESCRIPTION, "Shares a held Elite item on chat.")
+ .senderType(Player.class)
+ //permission is dealt inside of the command
+ .permission("elitemobs.shareitem")
+ .handler(commandContext -> ShareItem.showOnChat((Player) commandContext.getSender())));
+
+ // Base command builder
+ final Command.Builder builder = manager.commandBuilder("elitemobs", "em");
+
+ manager.command(builder.literal("help")
+ .argument(StringArgument.optional("query", StringArgument.StringMode.GREEDY))
+ .handler(context -> {
+ minecraftHelp.queryCommands(context.getOrDefault("query", ""), context.getSender());
+ }));
+
+ //// Create a world argument
+ //final CommandArgument worldArgument = WorldArgument.of("world");
+
+ // /em
+ manager.command(builder
+ .meta(CommandMeta.DESCRIPTION, "Opens the main player interface")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ if (DefaultConfig.isEmLeadsToStatusMenu())
+ new PlayerStatusScreen((Player) commandContext.getSender());
+ }));
+
+ new AdminCommands(manager, builder);
+ new UserCommands(manager, builder);
}
- public static boolean userPermCheck(String permission, CommandSender commandSender) {
-
- if (commandSender instanceof Player) {
-
- return permCheck(permission, commandSender);
-
- }
-
- commandSender.sendMessage("[EliteMobs] You may not run this command.");
- commandSender.sendMessage("[EliteMobs] This is a user command.");
- return false;
-
- }
-
- private static void validCommands(CommandSender commandSender) {
-
- if (commandSender instanceof Player) {
-
- Player player = (Player) commandSender;
-
- player.sendMessage("[EliteMobs] Valid commands:");
- if (silentPermCheck(STATS, commandSender))
- player.sendMessage("/elitemobs stats");
- if (silentPermCheck(SHOP, commandSender))
- player.sendMessage("/elitemobs shop");
- if (silentPermCheck(CUSTOMSHOP, commandSender))
- player.sendMessage("/elitemobs customshop");
- if (silentPermCheck(CURRENCY_WALLET, commandSender))
- player.sendMessage("/elitemobs wallet");
- if (silentPermCheck(CURRENCY_COINTOP, commandSender))
- player.sendMessage("/elitemobs cointop");
- if (silentPermCheck(CURRENCY_PAY, commandSender))
- player.sendMessage("/elitemobs pay [username]");
- if (silentPermCheck(CURRENCY_ADD, commandSender))
- player.sendMessage("/elitemobs add [username]");
- if (silentPermCheck(CURRENCY_SUBTRACT, commandSender))
- player.sendMessage("/elitemobs subtract [username]");
- if (silentPermCheck(CURRENCY_SET, commandSender))
- player.sendMessage("/elitemobs set [username]");
- if (silentPermCheck(CURRENCY_CHECK, commandSender))
- player.sendMessage("/elitemobs check [username]");
- if (silentPermCheck(RELOAD_CONFIGS, commandSender))
- player.sendMessage("/elitemobs reload");
- if (silentPermCheck(KILLALL_AGGRESSIVEELITES, commandSender))
- player.sendMessage("/elitemobs kill aggressive");
- if (silentPermCheck(KILLALL_PASSIVEELITES, commandSender))
- player.sendMessage("/elitemobs kill passive");
- if (silentPermCheck(SIMLOOT, commandSender))
- player.sendMessage("/elitemobs simloot [mob level]");
- if (silentPermCheck(GETLOOT, commandSender))
- player.sendMessage("/elitemobs getloot [loot name (no loot name = AdventurersGuildGUI)]");
- if (silentPermCheck(GIVELOOT, commandSender))
- player.sendMessage("/elitemobs giveloot [player name] random/[loot_name_underscore_for_spaces]");
- if (silentPermCheck(SPAWNMOB, commandSender))
- player.sendMessage("/elitemobs SpawnMob [mobType] [mobLevel] [mobPower] [mobPower2(keep adding as many as you'd like)]");
- if (silentPermCheck(SPAWN_BOSS_MOB, commandSender))
- commandSender.sendMessage("/elitemobs spawnBossMob [bossName]");
- if (silentPermCheck(CHECK_TIER, commandSender))
- commandSender.sendMessage("/elitemobs checktier");
- if (silentPermCheck(CHECK_MAX_TIER, commandSender))
- commandSender.sendMessage("/elitemobs checkmaxtier");
- if (silentPermCheck(SET_MAX_TIER, commandSender))
- commandSender.sendMessage("/elitemobs setmaxtier [tier]");
- if (silentPermCheck(GET_TIER, commandSender))
- commandSender.sendMessage("/elitemobs gettier [tier]");
-
-
- } else if (commandSender instanceof ConsoleCommandSender) {
-
- commandSender.sendMessage("[EliteMobs] Command not recognized. Valid commands:");
- commandSender.sendMessage("elitemobs stats");
- commandSender.sendMessage("elitemobs reload");
- commandSender.sendMessage("elitemobs check [username]");
- commandSender.sendMessage("elitemobs set [username]");
- commandSender.sendMessage("elitemobs add [username]");
- commandSender.sendMessage("elitemobs subtract [username]");
- commandSender.sendMessage("elitemobs killall passiveelites");
- commandSender.sendMessage("elitemobs killall aggressiveelites");
- commandSender.sendMessage("elitemobs giveloot [player name] random/[loot_name_underscore_for_spaces]");
- commandSender.sendMessage("elitemobs SpawnMob [worldName] [x] [y] [z] [mobType] [mobLevel] [mobPower] [mobPower2(keep adding as many as you'd like)]");
-
- }
-
- }
-
- private static boolean silentPermCheck(String permission, CommandSender commandSender) {
-
- return commandSender.hasPermission(permission);
-
- }
-
-
}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/CurrencyCommandsHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/CurrencyCommandsHandler.java
index 3dcb004a2..f48aaecc5 100644
--- a/src/main/java/com/magmaguy/elitemobs/commands/CurrencyCommandsHandler.java
+++ b/src/main/java/com/magmaguy/elitemobs/commands/CurrencyCommandsHandler.java
@@ -1,229 +1,146 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-import com.magmaguy.elitemobs.config.ConfigValues;
+import com.magmaguy.elitemobs.ChatColorConverter;
import com.magmaguy.elitemobs.config.EconomySettingsConfig;
+import com.magmaguy.elitemobs.config.TranslationConfig;
import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.economy.UUIDFilter;
-import com.magmaguy.elitemobs.playerdata.PlayerData;
-import org.bukkit.ChatColor;
+import com.magmaguy.elitemobs.utils.Round;
+import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.util.ArrayList;
-import java.util.UUID;
-
-import static org.bukkit.Bukkit.getServer;
-
/**
* Created by MagmaGuy on 17/06/2017.
*/
public class CurrencyCommandsHandler {
- public static void payCommand(String playerName, double amount) {
-
- if (amount > 0)
- EconomyHandler.addCurrency(UUIDFilter.guessUUI(playerName), amount);
-
-
- }
-
- public static void payCommand(Player commandSender, String[] args) {
-
- try {
-
- if (Double.parseDouble(args[2]) > 0 && Integer.parseInt(args[2]) <= EconomyHandler.checkCurrency(UUIDFilter.guessUUI(commandSender.getName()))) {
-
- payCommand(args[1], Integer.parseInt(args[2]));
- subtractCommand(commandSender.getName(), Integer.parseInt(args[2]));
-
- commandSender.sendMessage("You have paisd " + args[2] + " " + ConfigValues.economyConfig.get("Currency name") + " to " + args[1]);
- commandSender.sendMessage("You now have " + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(commandSender.getName())) + " " + ConfigValues.economyConfig.get("Currency name"));
-
- Player recipient = getServer().getPlayer(args[1]);
- recipient.sendMessage("You have received " + args[2] + " " + ConfigValues.economyConfig.get("Currency name") + " from " + commandSender.getDisplayName());
-
- } else if (Double.parseDouble(args[2]) < 0)
- commandSender.sendMessage("Nice try. This plugin doesn't make the same mistake as some banks have in the past.");
- else
- commandSender.sendMessage("You don't have enough " + ConfigValues.economyConfig.get("Currency name") + " to do that!");
-
-
- } catch (Exception e) {
-
- commandSender.sendMessage("Input not valid. Command format: /em pay [playerName] [amount]");
+ public static void payCommand(Player sender, String recipientName, double amount) {
+ //CASE: Negative amount
+ if (amount <= 0) {
+ sender.sendMessage(ChatColorConverter.convert("&4[EliteMobs]Nice try."));
+ return;
}
- }
-
- public static void addCommand(String playerName, double amount) {
-
- EconomyHandler.addCurrency(UUIDFilter.guessUUI(playerName), amount);
-
- }
-
- public static void addCommand(CommandSender commandSender, String[] args) {
-
- try {
-
- addCommand(args[1], Integer.parseInt(args[2]));
-
- commandSender.sendMessage("You have added " + args[2] + " to " + args[1]);
- commandSender.sendMessage("They now have " + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(commandSender.getName())));
-
- } catch (Exception e) {
-
- commandSender.sendMessage("Input not valid. Command format: /em add [playerName] [amount]");
-
+ //CASE: Offline player
+ Player recipient = Bukkit.getPlayer(recipientName);
+ if (recipient == null) {
+ sender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Player " + recipientName + " is not online and can therefore not get a payment."));
+ return;
}
- }
-
- public static void subtractCommand(String playerName, double amount) {
-
- EconomyHandler.subtractCurrency(UUIDFilter.guessUUI(playerName), amount);
-
- }
-
- public static void subtractCommand(CommandSender commandSender, String[] args) {
-
- try {
-
- subtractCommand(args[1], Integer.parseInt(args[2]));
-
- commandSender.sendMessage("You have subtracted " + args[2] + " from " + args[1]);
- commandSender.sendMessage("They now have " + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(commandSender.getName())));
-
- } catch (Exception e) {
-
- commandSender.sendMessage("Input not valid. Command format: /em subtract [playerName] [amount]");
-
+ //CASE: Insufficient funds
+ double senderCurrency = EconomyHandler.checkCurrency(sender.getUniqueId());
+ if (senderCurrency - amount < 0) {
+ sender.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyPaymentInsufficientCurrency()
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())));
+ return;
}
- }
-
- public static void setCommand(String playerName, double amount) {
-
- EconomyHandler.setCurrency(UUIDFilter.guessUUI(playerName), amount);
-
- }
-
- public static void setCommand(CommandSender commandSender, String[] args) {
-
- try {
-
- CurrencyCommandsHandler.setCommand(args[1], Integer.parseInt(args[2]));
- commandSender.sendMessage("You set " + args[1] + "'s " + ConfigValues.economyConfig.get("Currency name") + " to " + args[2]);
-
- } catch (Exception e) {
-
- commandSender.sendMessage("Input not valid. Command format: /em set [playerName] [amount]");
-
- }
+ double actuallyReceivedAmount = Round.twoDecimalPlaces(amount - amount * EconomySettingsConfig.getPlayerToPlayerTaxes());
+ double taxes = Round.twoDecimalPlaces(amount * EconomySettingsConfig.getPlayerToPlayerTaxes());
+
+ //CASE: Successful payment
+ EconomyHandler.addCurrency(recipient.getUniqueId(), actuallyReceivedAmount);
+ EconomyHandler.subtractCurrency(sender.getUniqueId(), amount);
+
+ sender.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyPayMessage()
+ .replace("$amount_sent", amount + "")
+ .replace("$amount_received", actuallyReceivedAmount + "")
+ .replace("$taxes", taxes + "")
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())
+ .replace("$receiver", recipient.getDisplayName())));
+
+ sender.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyCurrencyLeftMessage()
+ .replace("$amount_left", String.valueOf(EconomyHandler.checkCurrency(sender.getUniqueId())))
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())));
+
+ recipient.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyPaymentReceivedMessage()
+ .replace("$amount_sent", amount + "")
+ .replace("$amount_received", actuallyReceivedAmount + "")
+ .replace("$taxes", taxes + "")
+ .replace("$sender", sender.getDisplayName())
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())));
+
+ recipient.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyCurrencyLeftMessage()
+ .replace("$amount_left", String.valueOf(EconomyHandler.checkCurrency(recipient.getUniqueId())))
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())));
}
- public static Double checkCommand(String playerName) {
-
- return EconomyHandler.checkCurrency(UUIDFilter.guessUUI(playerName));
-
+ public static void addCommand(Player player, double amount) {
+ EconomyHandler.addCurrency(player.getUniqueId(), amount);
}
- public static void checkCommand(CommandSender commandSender, String[] args) {
-
- try {
- Double money = CurrencyCommandsHandler.checkCommand(args[1]);
- commandSender.sendMessage(args[1] + " has " + money + " " + ConfigValues.economyConfig.get("Currency name"));
- } catch (Exception e) {
- commandSender.sendMessage("Input not valid. Command format: /em check [playerName]");
+ public static void addCommand(CommandSender commandSender, String onlinePlayer, int amount) {
+ Player player = Bukkit.getPlayer(onlinePlayer);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Player " + onlinePlayer + " &4is not valid!"));
+ return;
}
-
+ addCommand(player, amount);
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2You have added " + amount + " to " + onlinePlayer));
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2They now have " + EconomyHandler.checkCurrency(player.getUniqueId())));
}
- public static Double walletCommand(String playerName) {
-
- return EconomyHandler.checkCurrency(UUIDFilter.guessUUI(playerName));
-
+ public static void addAllCommand(CommandSender commandSender, int amount) {
+ for (Player player : Bukkit.getOnlinePlayers())
+ addCommand(player, amount);
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2You have added " + amount + " to all online players."));
}
- public static void walletCommand(CommandSender commandSender, String[] args) {
-
- commandSender.sendMessage(ChatColor.GREEN + "You have " +
- CurrencyCommandsHandler.walletCommand(commandSender.getName()) + " " +
- ConfigValues.economyConfig.getString("Currency name"));
+ public static void subtractCommand(String playerName, double amount) {
+ EconomyHandler.subtractCurrency(Bukkit.getPlayer(playerName).getUniqueId(), amount);
}
- public static void coinTop(CommandSender commandSender) {
-
- ArrayList arrayList = new ArrayList();
-
- for (UUID uuid : PlayerData.playerCurrency.keySet()) {
-
- if (arrayList.size() == 0) {
-
- arrayList.add(uuid);
-
- } else {
-
- int index = arrayList.size();
-
- for (UUID inArrayUUID : arrayList) {
-
- double arrayEntryValue = PlayerData.playerCurrency.get(inArrayUUID);
- double newValue = PlayerData.playerCurrency.get(uuid);
-
- if (newValue > arrayEntryValue) {
-
- index = arrayList.indexOf(inArrayUUID);
- break;
-
- }
-
- }
-
- arrayList.add(index, uuid);
-
- }
-
+ public static void subtractCommand(CommandSender commandSender, String onlinePlayer, int amount) {
+ Player player = Bukkit.getPlayer(onlinePlayer);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Player " + onlinePlayer + " &4is not valid!"));
+ return;
}
+ subtractCommand(onlinePlayer, amount);
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2You have subtracted " + amount + " from " + onlinePlayer));
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]They now have " + EconomyHandler.checkCurrency(player.getUniqueId())));
+ }
- commandSender.sendMessage(ChatColor.RED + "[EliteMobs] " + ChatColor.DARK_GREEN + ConfigValues.economyConfig.get(EconomySettingsConfig.CURRENCY_NAME) + " High Score:");
-
- int iterationAmount = 10;
-
- if (arrayList.size() < 10) {
-
- iterationAmount = arrayList.size();
-
+ public static void setCommand(CommandSender commandSender, String onlinePlayer, double amount) {
+ Player player = Bukkit.getPlayer(onlinePlayer);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Player " + onlinePlayer + " &4is not valid!"));
+ return;
}
+ EconomyHandler.setCurrency(player.getUniqueId(), amount);
+ commandSender.sendMessage("You set " + onlinePlayer + "'s " + EconomySettingsConfig.getCurrencyName() + " to " + amount);
+ }
- for (int i = 0; i < iterationAmount; i++) {
-
- String name = PlayerData.playerDisplayName.get(arrayList.get(i));
- double amount = PlayerData.playerCurrency.get(arrayList.get(i));
-
- int place = i + 1;
-
- commandSender.sendMessage(ChatColor.GREEN + "#" + place + " " + ChatColor.WHITE + name + " with " +
- ChatColor.DARK_GREEN + amount + " " + ChatColor.GREEN + ConfigValues.economyConfig.get(EconomySettingsConfig.CURRENCY_NAME));
+ public static void checkCommand(CommandSender commandSender, String playerName) {
+ Player player = Bukkit.getPlayer(playerName);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Player " + playerName + " &4is not valid!"));
+ return;
}
+ double money = EconomyHandler.checkCurrency(player.getUniqueId());
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f " + playerName + " &2has " + money + " " + EconomySettingsConfig.getCurrencyName()));
+ }
+ public static void walletCommand(Player player) {
+ player.sendMessage(
+ ChatColorConverter.convert(
+ TranslationConfig.getEconomyWalletCommand()
+ .replace("$balance", String.valueOf(EconomyHandler.checkCurrency(player.getUniqueId())))
+ .replace("$currency_name", EconomySettingsConfig.getCurrencyName())));
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/CustomBossCommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/CustomBossCommandHandler.java
new file mode 100644
index 000000000..d0ec8e9fd
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/CustomBossCommandHandler.java
@@ -0,0 +1,75 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.RegionalBossEntity;
+import com.magmaguy.elitemobs.utils.DebugBlockLocation;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class CustomBossCommandHandler {
+ private CustomBossCommandHandler() {
+ }
+
+ public static Location autoSeekSafeSpawnLocation(Location originalLocation) {
+ Location newLocation = new Location(originalLocation.getWorld(),
+ originalLocation.getBlockX() + 0.5,
+ originalLocation.getBlockY() + 0.5,
+ originalLocation.getBlockZ() + 0.5);
+ for (int i = 0; i < 4; i++)
+ if (newLocation.add(new Vector(0, i, 0)).getBlock().isPassable()) {
+ new DebugBlockLocation(newLocation);
+ return newLocation;
+ }
+ return null;
+ }
+
+ public static void addSpawnLocation(String customBossConfigFieldsString, Player player) {
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfigFields.getRegionalElites().get(customBossConfigFieldsString);
+ if (customBossesConfigFields == null)
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed to add spawn location! Custom Boss " + customBossConfigFieldsString + " is not valid regional boss!"));
+ else {
+ Location safeSpawnLocation = autoSeekSafeSpawnLocation(player.getLocation());
+ if (safeSpawnLocation == null)
+ player.sendMessage("[EliteMobs] No safe spawn location found! Make sure the area is passable!");
+ else {
+ RegionalBossEntity.createPermanentRegionalBossEntity(customBossesConfigFields, safeSpawnLocation);
+ }
+ }
+ }
+
+ public static void addRelativeSpawnLocation(Player player, String customBossConfigFieldsString, String minidungeonString) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonString);
+ if (minidungeon == null) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed to add relative location! Minidungeon is not valid!"));
+ return;
+ }
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfigFields.getRegionalElites().get(customBossConfigFieldsString);
+ if (customBossesConfigFields == null)
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed to add relative location! Custom boss is not valid!"));
+ else {
+ Location safeSpawnLocation = autoSeekSafeSpawnLocation(player.getLocation());
+ if (safeSpawnLocation == null)
+ player.sendMessage("[EliteMobs] No safe spawn location found! Make sure the area is passable!");
+ else
+ minidungeon.initializeRelativeLocationAddition(customBossesConfigFields, safeSpawnLocation);
+ }
+ }
+
+ public static void setLeashRadius(String customBossConfigFieldsString, CommandSender commandSender, int leashRadius) {
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfigFields.getRegionalElites().get(customBossConfigFieldsString);
+ if (customBossesConfigFields == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed set the leash radius! Was the boss a valid regional boss?"));
+ return;
+ }
+ customBossesConfigFields.runtimeSetLeashRadius(leashRadius);
+ for (RegionalBossEntity regionalBossEntity : RegionalBossEntity.getRegionalBossEntitySet())
+ if (customBossesConfigFields.getFilename().equals(regionalBossEntity.getCustomBossesConfigFields().getFilename()))
+ regionalBossEntity.setLeashRadius(leashRadius);
+ }
+
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/DungeonCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/DungeonCommands.java
new file mode 100644
index 000000000..870fbc8c5
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/DungeonCommands.java
@@ -0,0 +1,26 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.api.PlayerPreTeleportEvent;
+import com.magmaguy.elitemobs.config.dungeonpackager.DungeonPackagerConfigFields;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+public class DungeonCommands {
+ public static void teleport(Player player, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ if (minidungeon != null)
+ if (minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType().equals(DungeonPackagerConfigFields.DungeonLocationType.SCHEMATIC))
+ PlayerPreTeleportEvent.teleportPlayer(player, minidungeon.getTeleportLocation());
+ else
+ PlayerPreTeleportEvent.teleportPlayer(player,
+ new Location(minidungeon.getTeleportLocation().getWorld(),
+ minidungeon.getTeleportLocation().getX(),
+ minidungeon.getTeleportLocation().getY(),
+ minidungeon.getTeleportLocation().getZ(),
+ Float.parseFloat("" + minidungeon.getDungeonPackagerConfigFields().getTeleportPointPitch()),
+ Float.parseFloat("" + minidungeon.getDungeonPackagerConfigFields().getTeleportPointYaw())));
+ else
+ player.sendMessage("[EliteMobs] That dungeon isn't valid!");
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/GetLootCommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/GetLootCommandHandler.java
deleted file mode 100644
index f18728d51..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/GetLootCommandHandler.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.items.uniqueitems.UniqueItemInitializer;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import static com.magmaguy.elitemobs.items.CustomItemConstructor.customItemList;
-
-/**
- * Created by MagmaGuy on 01/05/2017.
- */
-public class GetLootCommandHandler {
-
- public static boolean getLoot(Player player, String args1) {
-
- boolean itemExists = false;
-
- for (ItemStack itemStack : customItemList)
- itemExists = getItem(itemStack, args1, player);
-
- if (itemExists) return true;
-
- for (ItemStack itemStack : UniqueItemInitializer.uniqueItemsList)
- itemExists = getItem(itemStack, args1, player);
-
- if (itemExists) return true;
- return false;
-
- }
-
- private static boolean getItem(ItemStack itemStack, String args1, Player player) {
-
- String itemRawName = itemStack.getItemMeta().getDisplayName();
-
- if (itemRawName != null) {
-
- Bukkit.getLogger().info(itemStack.getItemMeta().getDisplayName());
-
- String itemProcessedName = itemRawName.replaceAll(" ", "_").toLowerCase();
- itemProcessedName = ChatColor.stripColor(itemProcessedName);
-
- if (itemProcessedName.equalsIgnoreCase(args1) && player.isValid()) {
-
- player.getInventory().addItem(itemStack);
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/GiveLootHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/GiveLootHandler.java
deleted file mode 100644
index 59619128e..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/GiveLootHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import org.bukkit.Bukkit;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-import static com.magmaguy.elitemobs.items.CustomItemConstructor.customItemList;
-
-public class GiveLootHandler {
-
- public static void giveLootCommand(CommandSender commandSender, String[] args) {
-
- if (Bukkit.getServer().getPlayer(args[1]) != null) {
-
- Player receiver = Bukkit.getServer().getPlayer(args[1]);
-
- if (args[2].equalsIgnoreCase("random") || args[2].equalsIgnoreCase("r")) {
-
- int index = ThreadLocalRandom.current().nextInt(customItemList.size());
- ItemStack itemStack = new ItemStack(customItemList.get(index));
- receiver.getInventory().addItem(itemStack);
-
- } else
- GetLootCommandHandler.getLoot(receiver, args[2]);
-
- } else
- commandSender.sendMessage("Can't give loot to player - player not found.");
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/GuildRankCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/GuildRankCommands.java
new file mode 100644
index 000000000..76afff26c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/GuildRankCommands.java
@@ -0,0 +1,31 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class GuildRankCommands {
+ public static void setGuildRank(CommandSender commandSender, String playerString, int prestigeLevel, int activeLevel) {
+
+ Player player = Bukkit.getPlayer(playerString);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4The player isn't online!"));
+ return;
+ }
+
+ if (activeLevel < 0 || activeLevel > 10 + prestigeLevel || prestigeLevel > 10 || activeLevel > 20) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4The prestige rank / guild rank combination you picked is not valid!"));
+ return;
+ }
+
+ GuildRank.setGuildPrestigeRank(player, prestigeLevel);
+ GuildRank.setMaxGuildRank(player, activeLevel);
+ GuildRank.setActiveGuildRank(player, activeLevel);
+
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2You set the EliteMobs rank of " +
+ playerString + " to " + GuildRank.getRankName(GuildRank.getGuildPrestigeRank(player), GuildRank.getActiveGuildRank(player))));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/KillHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/KillHandler.java
deleted file mode 100644
index cc6fd731a..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/KillHandler.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.EliteMobs;
-import com.magmaguy.elitemobs.EntityTracker;
-import com.magmaguy.elitemobs.mobconstructor.EliteMobEntity;
-import org.bukkit.World;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Entity;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-
-public class KillHandler {
-
- public static void killCommand(CommandSender commandSender, String[] args) {
-
- if (args.length < 2)
- commandSender.sendMessage("[EliteMobs] Incorrect command syntax. Try /em kill aggressive/passive/mobType [radius]");
-
- /*
- Run with no radius search
- */
- if (args.length == 2) {
- if (args[1].equalsIgnoreCase("aggressive"))
- killAggressiveMobs(commandSender);
- else if (args[1].equalsIgnoreCase("passive"))
- killPassiveMobs(commandSender);
- else
- killEntityType(commandSender, args);
- return;
- }
-
- /*
- Run radius search
- */
- if (args.length == 3) {
- if (args[1].equalsIgnoreCase("aggressive"))
- radiusKillAggressiveMobs(commandSender, args);
- else if (args[1].equalsIgnoreCase("passive"))
- radiusKillPassiveMobs(commandSender, args);
- else
- radiusKillSpecificMobs(commandSender, args);
- } else
- commandSender.sendMessage("[EliteMobs] Incorrect command syntax. Try /em kill aggressive/passive/mobType [radius]");
-
-
- }
-
- private static void killAggressiveMobs(CommandSender commandSender) {
-
- if (CommandHandler.permCheck(CommandHandler.KILLALL_AGGRESSIVEELITES, commandSender)) {
- int counter = 0;
-
- for (EliteMobEntity eliteMobEntity : EntityTracker.getEliteMobs()) {
- eliteMobEntity.getLivingEntity().remove();
- EntityTracker.unregisterEliteMob(eliteMobEntity);
- counter++;
- }
-
-
- commandSender.sendMessage("Killed " + counter + " Elite Mobs.");
-
- }
-
- }
-
- private static void killPassiveMobs(CommandSender commandSender) {
-
- if (CommandHandler.permCheck(CommandHandler.KILLALL_PASSIVEELITES, commandSender)) {
- int counter = 0;
- for (World world : EliteMobs.validWorldList)
- for (LivingEntity livingEntity : world.getLivingEntities())
- if (EntityTracker.isSuperMob(livingEntity)) {
- livingEntity.remove();
- counter++;
- }
-
- commandSender.sendMessage("Killed " + counter + " Elite Mobs.");
-
- }
- }
-
- private static void killEntityType(CommandSender commandSender, String[] args) {
-
- if (CommandHandler.permCheck(CommandHandler.KILLALL_SPECIFICENTITY, commandSender)) {
-
- try {
- EntityType entityType = EntityType.fromName(args[1].toUpperCase());
- int counter = 0;
- for (World world : EliteMobs.validWorldList)
- for (LivingEntity livingEntity : world.getLivingEntities())
- if (livingEntity.getType().equals(entityType) &&
- (EntityTracker.isEliteMob(livingEntity) ||
- EntityTracker.isSuperMob(livingEntity))) {
- livingEntity.remove();
- counter++;
- }
-
- commandSender.sendMessage("Killed " + counter + " Elite " + args[1] + ".");
-
- } catch (Exception e) {
- commandSender.sendMessage("[EliteMobs] Entity type is not valid!");
- }
-
- }
-
- }
-
- private static void radiusKillAggressiveMobs(CommandSender commandSender, String[] args) {
-
- if (!CommandHandler.userPermCheck(CommandHandler.KILLALL_AGGRESSIVEELITES, commandSender))
- return;
-
- try {
-
- int counter = 0;
- for (Entity entity : ((Player) commandSender).getNearbyEntities(Integer.parseInt(args[2]), Integer.parseInt(args[2]), Integer.parseInt(args[2])))
- if (EntityTracker.isEliteMob(entity)) {
- entity.remove();
- counter++;
- }
-
- commandSender.sendMessage("Killed " + counter + " Elite Mobs.");
-
- } catch (Exception e) {
- commandSender.sendMessage("[EliteMobs] Incorrect command syntax. Try /em kill aggressive/passive/mobType [radius]");
- }
-
- }
-
- private static void radiusKillPassiveMobs(CommandSender commandSender, String[] args) {
-
- if (!CommandHandler.userPermCheck(CommandHandler.KILLALL_PASSIVEELITES, commandSender))
- return;
-
- try {
- int counter = 0;
- for (Entity entity : ((Player) commandSender).getNearbyEntities(Integer.parseInt(args[2]), Integer.parseInt(args[2]), Integer.parseInt(args[2])))
- if (EntityTracker.isSuperMob(entity)) {
- entity.remove();
- counter++;
- }
- commandSender.sendMessage("Killed " + counter + " Elite Mobs.");
-
- } catch (Exception e) {
- commandSender.sendMessage("[EliteMobs] Incorrect command syntax. Try /em kill aggressive/passive/mobType [radius]");
- }
-
- }
-
- private static void radiusKillSpecificMobs(CommandSender commandSender, String[] args) {
-
- if (!CommandHandler.userPermCheck(CommandHandler.KILLALL_SPECIFICENTITY, commandSender))
- return;
-
- try {
-
- EntityType entityType = EntityType.fromName(args[1].toUpperCase());
-
- int counter = 0;
- for (Entity entity : ((Player) commandSender).getNearbyEntities(Integer.parseInt(args[2]), Integer.parseInt(args[2]), Integer.parseInt(args[2])))
- if (entity.getType().equals(entityType) &&
- (EntityTracker.isEliteMob(entity) ||
- EntityTracker.isSuperMob(entity))) {
- entity.remove();
- counter++;
- }
- commandSender.sendMessage("Killed " + counter + " Elite " + args[1] + ".");
-
- } catch (Exception e) {
- commandSender.sendMessage("[EliteMobs] Incorrect command syntax. Try /em kill aggressive/passive/mobType [radius]");
- }
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/LootGUI.java b/src/main/java/com/magmaguy/elitemobs/commands/LootGUI.java
deleted file mode 100644
index e43a8f8c7..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/LootGUI.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.items.CustomItemConstructor;
-import com.magmaguy.elitemobs.items.uniqueitems.UniqueItemInitializer;
-import org.bukkit.Bukkit;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.ItemMeta;
-import org.bukkit.inventory.meta.SkullMeta;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Created by MagmaGuy on 04/05/2017.
- */
-public class LootGUI implements Listener {
-
- private int currentHeaderPage = 1;
- private int currentLootPage = 1;
- private boolean filter = false;
- private int filterRank = 0;
-
- private List lootSlots = new ArrayList<>(Arrays.asList(10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31,
- 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 46, 47, 48, 49, 50, 51, 52));
-
- private String shopName = "EliteMobs Custom Loot";
-
- public void lootGUI(Player player) {
-
- Inventory fakeChestInventory = Bukkit.createInventory(null, 54, shopName);
- tierConstructor(fakeChestInventory);
- headerConstructor(fakeChestInventory);
- lootNavigationConstructor(fakeChestInventory);
- lootConstructor(fakeChestInventory);
-
- player.openInventory(fakeChestInventory);
-
- }
-
- private void headerConstructor(Inventory inventory) {
-
- ItemStack arrowLeft = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta arrowLeftSkullMeta = (SkullMeta) arrowLeft.getItemMeta();
- arrowLeftSkullMeta.setOwner("MHF_ArrowLeft");
- arrowLeftSkullMeta.setDisplayName("Previous Item Ranks");
- arrowLeft.setItemMeta(arrowLeftSkullMeta);
-
- inventory.setItem(0, arrowLeft);
-
-
- ItemStack arrowRight = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta arrowRightSkullMeta = (SkullMeta) arrowRight.getItemMeta();
- arrowRightSkullMeta.setOwner("MHF_ArrowRight");
- arrowRightSkullMeta.setDisplayName("Next Item Ranks");
- arrowRight.setItemMeta(arrowRightSkullMeta);
-
- inventory.setItem(8, arrowRight);
-
-
- ItemStack signature = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta signatureSkullMeta = (SkullMeta) signature.getItemMeta();
- signatureSkullMeta.setOwner("magmaguy");
- signatureSkullMeta.setDisplayName("EliteMobs by MagmaGuy");
- List signatureList = new ArrayList<>();
- signatureList.add("Support the plugins you enjoy!");
- signatureSkullMeta.setLore(signatureList);
- signature.setItemMeta(signatureSkullMeta);
-
- inventory.setItem(4, signature);
-
- }
-
- private void tierConstructor(Inventory inventory) {
-
- List tierSlots = new ArrayList<>();
-
- tierSlots.add(1);
- tierSlots.add(2);
- tierSlots.add(3);
- tierSlots.add(5);
- tierSlots.add(6);
- tierSlots.add(7);
-
- List keySet = new ArrayList<>(CustomItemConstructor.dynamicRankedItemStacks.keySet());
-
- int counter = 1;
-
- for (int number : tierSlots) {
-
- if (keySet.size() >= counter + ((currentHeaderPage - 1) * 6)) {
-
- ItemStack chest = new ItemStack(Material.CHEST, 1);
- ItemMeta chestItemMeta = chest.getItemMeta();
- chestItemMeta.setDisplayName("Tier " + keySet.get((counter - 1) + ((currentHeaderPage - 1) * 6)));
- List lore = new ArrayList();
- lore.add("Filter by items of this rank.");
- chestItemMeta.setLore(lore);
- chest.setItemMeta(chestItemMeta);
-
- inventory.setItem(number, chest);
-
- }
-
- counter++;
-
- }
-
- }
-
- private void lootNavigationConstructor(Inventory inventory) {
-
- ItemStack arrowLeft = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta arrowLeftSkullMeta = (SkullMeta) arrowLeft.getItemMeta();
- arrowLeftSkullMeta.setOwner("MHF_ArrowLeft");
- arrowLeftSkullMeta.setDisplayName("Previous Loot Page");
- arrowLeft.setItemMeta(arrowLeftSkullMeta);
-
- inventory.setItem(27, arrowLeft);
-
-
- ItemStack arrowRight = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta arrowRightSkullMeta = (SkullMeta) arrowRight.getItemMeta();
- arrowRightSkullMeta.setOwner("MHF_ArrowRight");
- arrowRightSkullMeta.setDisplayName("Next Loot Page");
- arrowRight.setItemMeta(arrowRightSkullMeta);
-
- inventory.setItem(35, arrowRight);
-
- }
-
- private void lootConstructor(Inventory inventory) {
-
- List getLootList = new ArrayList<>();
- for (List list : CustomItemConstructor.dynamicRankedItemStacks.values())
- getLootList.addAll(list);
-
- getLootList.addAll(CustomItemConstructor.staticCustomItemHashMap.keySet());
- getLootList.addAll(UniqueItemInitializer.uniqueItemsList);
-
- int counter = 1;
-
- for (int number : lootSlots) {
-
- if (!filter) {
-
- if (getLootList.size() >= counter + ((currentLootPage - 1) * 35)) {
-
- inventory.setItem(number, getLootList.get(counter - 1 + ((currentLootPage - 1) * 35)));
-
- }
-
- } else {
-
- List currentRankloot = CustomItemConstructor.dynamicRankedItemStacks.get(filterRank);
-
- if (currentRankloot.size() >= counter + ((currentLootPage - 1) * 35)) {
-
- inventory.setItem(number, currentRankloot.get(counter - 1 + ((currentLootPage - 1) * 35)));
-
- }
-
- }
-
- counter++;
-
- }
-
- }
-
- @EventHandler
- public void onClick(InventoryClickEvent event) {
-
- if (event.getInventory().getName().equalsIgnoreCase(shopName)) {
-
- if (event.getCurrentItem() == null || event.getCurrentItem().getType().equals(Material.AIR)) {
-
- event.setCancelled(true);
- return;
-
- }
-
- String itemDisplayName = event.getCurrentItem().getItemMeta().getDisplayName();
- Player player = (Player) event.getWhoClicked();
-
- if (itemDisplayName != null) {
-
- if (itemDisplayName.equals("Next Loot Page")) {
-
- currentLootPage++;
- lootGUI(player);
-
- } else if (itemDisplayName.equals("Previous Loot Page")) {
-
- if (currentLootPage > 1) {
-
- currentLootPage--;
- lootGUI(player);
-
- }
-
- } else if (itemDisplayName.equals("Next Item Ranks")) {
-
- currentHeaderPage++;
- lootGUI(player);
-
- } else if (itemDisplayName.equals("Previous Item Ranks")) {
-
- if (currentHeaderPage > 1) {
-
- currentHeaderPage--;
- lootGUI(player);
-
- }
-
- } else if (itemDisplayName.equals("EliteMobs by MagmaGuy")) {
-
- filter = false;
- currentLootPage = 1;
- lootGUI(player);
-
- } else if (event.getCurrentItem().getItemMeta().getLore().get(0).equals("Filter by items of this rank.")) {
-
- filter = true;
- String[] lore = itemDisplayName.split("\\s");
- filterRank = Integer.valueOf(lore[1]);
- currentLootPage = 1;
- lootGUI(player);
-
- }
-
- }
-
- if (lootSlots.contains(event.getSlot())) {
-
- player.getInventory().addItem(event.getCurrentItem());
-
- }
-
- event.setCancelled(true);
-
- }
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/ReloadConfigCommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/ReloadConfigCommandHandler.java
deleted file mode 100644
index af9977664..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/ReloadConfigCommandHandler.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.items.CustomItemConstructor;
-import org.bukkit.Bukkit;
-
-/**
- * Created by MagmaGuy on 13/05/2017.
- */
-public class ReloadConfigCommandHandler {
-
- public void reloadConfiguration() {
-
- //Reload all configs
- ConfigValues.initializeCachedConfigurations();
-
- //reload config-based initialized data
- CustomItemConstructor customItemConstructor = new CustomItemConstructor();
- customItemConstructor.superDropParser();
-
- Bukkit.getLogger().info("EliteMobs config reloaded!");
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/ReloadHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/ReloadHandler.java
deleted file mode 100644
index 77d208483..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/ReloadHandler.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.items.CustomItemConstructor;
-import com.magmaguy.elitemobs.items.uniqueitems.UniqueItemInitializer;
-import org.bukkit.command.CommandSender;
-
-public class ReloadHandler {
-
- public static void reloadCommand(CommandSender commandSender, String[] args) {
-
- ConfigValues.initializeCachedConfigurations();
- CustomItemConstructor.customItemList.clear();
- CustomItemConstructor.staticCustomItemHashMap.clear();
- CustomItemConstructor.dynamicRankedItemStacks.clear();
- UniqueItemInitializer.uniqueItemsList.clear();
- CustomItemConstructor customItemConstructor = new CustomItemConstructor();
- customItemConstructor.superDropParser();
-// UniqueItemConstructor uniqueItemConstructor = new UniqueItemConstructor();
-// uniqueItemConstructor.intializeUniqueItems();
- UniqueItemInitializer.initialize();
- commandSender.sendMessage("EliteMobs reloaded!");
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/SetMaxItemTierCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/SetMaxItemTierCommand.java
deleted file mode 100644
index 9d84fdb8c..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/SetMaxItemTierCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.ChatColorConverter;
-import com.magmaguy.elitemobs.config.*;
-import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.Configuration;
-
-public class SetMaxItemTierCommand {
-
- public static void setMaxItemTier(double tier, CommandSender commandSender) {
-
- CustomConfigLoader customConfigLoader = new CustomConfigLoader();
- Configuration itemsDropSettingsConfig = customConfigLoader.getCustomConfig(ItemsDropSettingsConfig.CONFIG_NAME);
-
- itemsDropSettingsConfig.set(ItemsDropSettingsConfig.MAXIMUM_LOOT_TIER, tier);
- customConfigLoader.saveCustomConfig(ItemsDropSettingsConfig.CONFIG_NAME);
-
- CustomConfigLoader customConfigLoader1 = new CustomConfigLoader();
- Configuration itemsProceduralSettingsConfig = customConfigLoader1.getCustomConfig(ItemsProceduralSettingsConfig.CONFIG_NAME);
-
- itemsProceduralSettingsConfig.set(ItemsProceduralSettingsConfig.ARROW_DAMAGE_MAX_LEVEL, tier-1);
- itemsProceduralSettingsConfig.set(ItemsProceduralSettingsConfig.DAMAGE_ALL_MAX_LEVEL, tier-1);
- itemsProceduralSettingsConfig.set(ItemsProceduralSettingsConfig.PROTECTION_ENVIRONMENTAL_MAX_LEVEL, tier-1);
- customConfigLoader1.saveCustomConfig(ItemsProceduralSettingsConfig.CONFIG_NAME);
-
-
- int maxMobLevel = (int) (tier * ConfigValues.mobCombatSettingsConfig.getDouble(MobCombatSettingsConfig.PER_TIER_LEVEL_INCREASE) * 10);
-
- CustomConfigLoader customConfigLoader2 = new CustomConfigLoader();
- Configuration mobCombatSettingsConfig = customConfigLoader2.getCustomConfig(MobCombatSettingsConfig.CONFIG_NAME);
- mobCombatSettingsConfig.set(MobCombatSettingsConfig.NATURAL_ELITEMOB_LEVEL_CAP, maxMobLevel);
- customConfigLoader2.saveCustomConfig(MobCombatSettingsConfig.CONFIG_NAME);
-
- ConfigValues.initializeCachedConfigurations();
-
- commandSender.sendMessage(ChatColorConverter.convert(
- "Warning: You have set the max tier to " + tier + "!"));
- commandSender.sendMessage(ChatColorConverter.convert(
- "The max protection enchantment has been increased to " + (tier - 1)));
- commandSender.sendMessage(ChatColorConverter.convert(
- "The max sharpness enchantment has been increased to " + (tier- 1)));
- commandSender.sendMessage(ChatColorConverter.convert(
- "The max power enchantment has been increased to " + (tier - 1)));
- commandSender.sendMessage(ChatColorConverter.convert(
- "The max mob level has been increased to " + maxMobLevel));
- commandSender.sendMessage(ChatColorConverter.convert(
- "You can run this command again to tweak the values or change them in the ItemProceduralSettings.yml file," +
- " as well as the ItemsDropSettings and the MobCombatSettings"));
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/SetupHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/SetupHandler.java
new file mode 100644
index 000000000..a1d5f604e
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/SetupHandler.java
@@ -0,0 +1,75 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.EliteMobs;
+import com.magmaguy.elitemobs.commands.setup.SetupMenu;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+public class SetupHandler {
+
+ public static void setupMenuCommand(Player player) {
+ new SetupMenu(player);
+ }
+
+ public static void setupMinidungeonCommand(Player player, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ minidungeon.finalizeMinidungeonInstallation(player, true);
+ player.performCommand("/rotate " + minidungeon.getDungeonPackagerConfigFields().getRotation());
+ player.performCommand("/paste");
+ }
+
+ public static void setupMinidungeonNoPasteCommand(Player player, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ minidungeon.finalizeMinidungeonInstallation(player, false);
+ }
+
+ public static void setupUnminidungeonCommand(Player player, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ minidungeon.uninstallSchematicMinidungeon(player);
+ player.performCommand("/undo");
+ }
+
+ public static void setupUnminidungeonNoPasteCommand(Player player, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ minidungeon.finalizeMinidungeonInstallation(player, false);
+ }
+
+ public static void setupAreaCommand(Player player, String regionName) {
+ if (!EliteMobs.worldGuardIsEnabled) {
+ player.sendMessage("[EliteMobs] You don't have WorldGuard installed! It is not possible to correctly set " +
+ "up a lair/minidungeon/dungeon without that plugin!");
+ return;
+ }
+ if (!WorldGuardCompatibility.protectMinidungeonArea(regionName, player.getLocation())) {
+ player.sendMessage(ChatColorConverter.convert("&4[EliteMobs] Failed to protect region! Was the region name correct?"));
+ //worldguardextraflags
+ if (Bukkit.getPluginManager().isPluginEnabled("WorldGuardExtraFlags")) {
+ commandPackage("&2", "fly", "deny", player, regionName);
+ } else {
+ player.sendMessage(ChatColor.RED + "[EliteMobs] Warning: the WorldGuardExtraFlags plugin is not present. It is recommended for the use of the anti-flight flag.");
+ }
+
+ player.performCommand("rg info");
+ } else
+ player.sendMessage(ChatColorConverter.convert("&2[EliteMobs] Set all WorldGuard flags correctly!"));
+
+ }
+
+ private static void commandPackage(String colorCode, String flagString, String state, Player player, String regionName) {
+ player.sendMessage(flagString(colorCode + flagString, player));
+ player.performCommand(commandString(flagString, state, player, regionName));
+ }
+
+ private static String flagString(String flagString, Player player) {
+ return ChatColorConverter.convert("&a[EliteMobs] Adding flag " + flagString);
+ }
+
+ private static String commandString(String flagString, String state, Player player, String regionName) {
+ return "region flag " + regionName + " " + flagString + " " + state;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/SimLootHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/SimLootHandler.java
deleted file mode 100644
index 62ae75a82..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/SimLootHandler.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import org.bukkit.entity.Player;
-
-/**
- * Created by MagmaGuy on 08/06/2017.
- */
-public class SimLootHandler {
-
- public static void simLoot(Player player, int level) {
-
-// if (level < 1)
-// level = 0;
-//
-// LootTables.generateLoot(player);
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/SpawnCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/SpawnCommand.java
new file mode 100644
index 000000000..bec8a6a01
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/SpawnCommand.java
@@ -0,0 +1,178 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfig;
+import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.SuperMobConstructor;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.passivemobs.SuperMobProperties;
+import com.magmaguy.elitemobs.powers.meta.ElitePower;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.util.Vector;
+
+import java.util.HashSet;
+import java.util.Optional;
+
+/**
+ * Created by MagmaGuy on 01/05/2017.
+ */
+public class SpawnCommand {
+
+ public static void spawnEliteEntityTypeCommand(Player player, EntityType entityType, Integer level, String[] powers) {
+ LivingEntity livingEntity = (LivingEntity) player.getLocation().getWorld().spawnEntity(getLocation(player), entityType);
+ HashSet mobPowers = getPowers(powers, player);
+ EliteEntity eliteEntity = new EliteEntity();
+ eliteEntity.setLevel(level);
+ eliteEntity.setLivingEntity(livingEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
+ if (!mobPowers.isEmpty()) eliteEntity.applyPowers(mobPowers);
+ else eliteEntity.randomizePowers(EliteMobProperties.getPluginData(livingEntity));
+ }
+
+ public static void spawnEliteEntityTypeCommand(CommandSender commandSender,
+ EntityType entityType,
+ String world,
+ Vector coords,
+ Integer level,
+ Optional powers) {
+ try {
+ Location location = new Location(Bukkit.getWorld(world), coords.getX(), coords.getY(), coords.getZ());
+ spawnEliteEntityTypeCommand(commandSender,
+ location,
+ entityType,
+ level,
+ powers);
+ } catch (Exception e) {
+ commandSender.sendMessage("[EliteMobs] World argument was not valid!");
+ }
+ }
+
+ public static void spawnEliteEntityTypeCommand(CommandSender commandSender,
+ Location location,
+ EntityType entityType,
+ Integer level,
+ Optional powers) {
+ if (!EliteMobProperties.getValidMobTypes().contains(entityType)) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Entity type " + entityType.toString() + " can't be an Elite!"));
+ return;
+ }
+ LivingEntity livingEntity = (LivingEntity) location.getWorld().spawnEntity(location, entityType);
+ HashSet mobPowers = new HashSet<>();
+ if (powers.isPresent())
+ mobPowers = getPowers(powers.get(), commandSender);
+ EliteEntity eliteEntity = new EliteEntity();
+ eliteEntity.setLevel(level);
+ eliteEntity.setLivingEntity(livingEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
+ if (!mobPowers.isEmpty()) eliteEntity.applyPowers(mobPowers);
+ else eliteEntity.randomizePowers(EliteMobProperties.getPluginData(livingEntity));
+ }
+
+ public static void spawnCustomBossCommand(CommandSender commandSender,
+ String fileName,
+ String world,
+ Vector coords) {
+ try {
+ Location location = new Location(Bukkit.getWorld(world), coords.getX(), coords.getY(), coords.getZ());
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfig.getCustomBoss(fileName);
+ if (customBossesConfigFields == null) {
+ commandSender.sendMessage("Filename " + fileName + " is not valid! Make sure you are writing the name of a configuration file in the custombosses folder!");
+ return;
+ }
+ CustomBossEntity customBossEntity = new CustomBossEntity(customBossesConfigFields);
+ customBossEntity.setSpawnLocation(location);
+ customBossEntity.spawn(false);
+ } catch (Exception e) {
+ commandSender.sendMessage("[EliteMobs] World argument was not valid!");
+ }
+
+ }
+
+ public static void spawnCustomBossCommand(CommandSender commandSender,
+ String fileName,
+ String world,
+ Vector coords,
+ int level) {
+ try {
+ Location location = new Location(Bukkit.getWorld(world), coords.getX(), coords.getY(), coords.getZ());
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfig.getCustomBoss(fileName);
+ if (customBossesConfigFields == null) {
+ commandSender.sendMessage("Filename " + fileName + " is not valid! Make sure you are writing the name of a configuration file in the custombosses folder!");
+ return;
+ }
+ CustomBossEntity customBossEntity = new CustomBossEntity(customBossesConfigFields);
+ customBossEntity.setSpawnLocation(location);
+ customBossEntity.setLevel(level);
+ customBossEntity.spawn(false);
+ } catch (Exception e) {
+ commandSender.sendMessage("[EliteMobs] World argument was not valid!");
+ }
+
+ }
+
+ public static void spawnCustomBossCommand(Player player, String fileName, int level) {
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfig.getCustomBoss(fileName);
+ if (customBossesConfigFields == null) {
+ player.sendMessage("Filename " + fileName + " is not valid! Make sure you are writing the name of a configuration file in the custombosses folder!");
+ return;
+ }
+ CustomBossEntity customBossEntity = new CustomBossEntity(customBossesConfigFields);
+ customBossEntity.setSpawnLocation(getLocation(player));
+ customBossEntity.setLevel(level);
+ customBossEntity.spawn(false);
+ }
+
+ public static void spawnCustomBossCommand(Player player, String fileName) {
+ CustomBossesConfigFields customBossesConfigFields = CustomBossesConfig.getCustomBoss(fileName);
+ if (customBossesConfigFields == null) {
+ player.sendMessage("Filename " + fileName + " is not valid! Make sure you are writing the name of a configuration file in the custombosses folder!");
+ return;
+ }
+ CustomBossEntity customBossEntity = new CustomBossEntity(customBossesConfigFields);
+ customBossEntity.setSpawnLocation(getLocation(player));
+ customBossEntity.spawn(false);
+ }
+
+ public static void spawnSuperMobCommand(Player player, EntityType entityType) {
+ if (SuperMobProperties.isValidSuperMobType(entityType))
+ spawnSuperMob(entityType, getLocation(player));
+ else
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Entity type " + entityType.toString() + " can't be a Super Mob!"));
+ }
+
+ private static Location getLocation(Player player) {
+ return player.getTargetBlock(null, 30).getLocation().add(0.5, 1, 0.5);
+ }
+
+ private static HashSet getPowers(String[] mobPowers, CommandSender commandSender) {
+
+ HashSet elitePowers = new HashSet<>();
+
+ if (mobPowers.length > 0)
+ for (String string : mobPowers) {
+ ElitePower elitePower = ElitePower.getElitePower(string);
+ if (elitePower == null) {
+ commandSender.sendMessage("[EliteMobs] Power " + string + " is not a valid power! Valid powers:");
+ StringBuilder allPowers = new StringBuilder();
+ for (ElitePower iteratedPower : ElitePower.getElitePowers())
+ allPowers.append(iteratedPower.getName()).append(", ");
+ allPowers.append("custom");
+ commandSender.sendMessage(allPowers.toString());
+ return new HashSet<>();
+ }
+ elitePowers.add(elitePower);
+ }
+ return elitePowers;
+ }
+
+ private static void spawnSuperMob(EntityType entityType, Location location) {
+ SuperMobConstructor.constructSuperMob((LivingEntity) location.getWorld().spawnEntity(location, entityType));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/SpawnMobCommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/SpawnMobCommandHandler.java
deleted file mode 100644
index f1a072e90..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/SpawnMobCommandHandler.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.events.mobs.*;
-import com.magmaguy.elitemobs.mobconstructor.EliteMobEntity;
-import com.magmaguy.elitemobs.mobconstructor.SuperMobConstructor;
-import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
-import com.magmaguy.elitemobs.mobconstructor.mobdata.passivemobs.SuperMobProperties;
-import com.magmaguy.elitemobs.mobpowers.ElitePower;
-import com.magmaguy.elitemobs.mobpowers.defensivepowers.*;
-import com.magmaguy.elitemobs.mobpowers.majorpowers.*;
-import com.magmaguy.elitemobs.mobpowers.miscellaneouspowers.BonusLoot;
-import com.magmaguy.elitemobs.mobpowers.miscellaneouspowers.MovementSpeed;
-import com.magmaguy.elitemobs.mobpowers.miscellaneouspowers.Taunt;
-import com.magmaguy.elitemobs.mobpowers.offensivepowers.*;
-import org.bukkit.Location;
-import org.bukkit.World;
-import org.bukkit.command.BlockCommandSender;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-import org.bukkit.entity.Squid;
-import org.bukkit.util.Vector;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-
-import static com.magmaguy.elitemobs.EliteMobs.validWorldList;
-
-/**
- * Created by MagmaGuy on 01/05/2017.
- */
-public class SpawnMobCommandHandler {
-
- public static void spawnMob(CommandSender commandSender, String[] args) {
-
- Location location = getLocation(commandSender, args);
- if (location == null) return;
-
- EntityType entityType = getEntityType(commandSender, args);
- if (entityType == null) return;
-
- if (SuperMobProperties.isValidSuperMobType(entityType)) {
- spawnSuperMob(entityType, location);
- return;
- }
-
- Integer mobLevel = getLevel(commandSender, args);
- if (mobLevel == null) return;
-
- HashSet mobPowers = getPowers(commandSender, args);
-
- EliteMobEntity eliteMobEntity = new EliteMobEntity(entityType, location, mobLevel, mobPowers);
-
- }
-
- private static Location getLocation(CommandSender commandSender, String args[]) {
-
- if (commandSender instanceof Player)
- return getLocation((Player) commandSender);
-
-
- if (commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender) {
-
- World world = null;
-
- try {
-
- for (World worldIterator : validWorldList)
- if (worldIterator.getName().equals(args[1]))
- world = worldIterator;
-
- } catch (Exception e) {
-
- commandSender.sendMessage("[EliteMobs] Invalid world name when summoning Elite Mob.");
- commandSender.sendMessage("[EliteMobs] Valid worlds:");
- for (World worldIterator : validWorldList)
- commandSender.sendMessage(worldIterator.getName());
- commandSender.sendMessage("[EliteMobs] Is your world enabled in the ValidWorlds.yml config file?");
- return null;
-
- }
-
- double xCoord, yCoord, zCoord;
-
- try {
-
- xCoord = Double.parseDouble(args[2]);
- yCoord = Double.parseDouble(args[3]);
- zCoord = Double.parseDouble(args[4]);
-
- } catch (Exception e) {
-
- commandSender.sendMessage("[EliteMobs] Invalid X Y Z coordinates.");
- return null;
-
- }
-
- return new Location(world, xCoord, yCoord, zCoord);
-
- }
-
- return null;
-
- }
-
- private static Location getLocation(Player player) {
- return player.getTargetBlock(null, 30).getLocation().add(0.5, 1, 0.5);
- }
-
-
- private static EntityType getEntityType(CommandSender commandSender, String args[]) {
-
- String entityInput = "";
-
- if (commandSender instanceof Player) {
-
- try {
-
- entityInput = args[1].toLowerCase();
-
- } catch (Exception e) {
-
- commandSender.sendMessage("[EliteMobs] Error trying to obtain mob type.");
- String validEntities = "";
- for (EntityType entities : EliteMobProperties.getValidMobTypes())
- validEntities += entities + ", ";
- commandSender.sendMessage("[EliteMobs] Valid mob types:" + validEntities);
-
- }
-
-
- } else if (commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender) {
-
-
- try {
-
- entityInput = args[5].toLowerCase();
-
- } catch (Exception e) {
-
- commandSender.sendMessage("[EliteMobs] Error trying to obtain mob type.");
- String validEntities = "";
- for (EntityType entities : EliteMobProperties.getValidMobTypes())
- validEntities += entities + ", ";
- commandSender.sendMessage("[EliteMobs] Valid mob types:" + validEntities);
-
- }
-
- }
-
- try {
- return EntityType.valueOf(entityInput.toUpperCase());
- } catch (Exception ex) {
- commandSender.sendMessage("[EliteMobs] Could not spawn mob type " + entityInput +
- " If this is incorrect, please contact the dev.");
- return null;
- }
-
- }
-
- private static Integer getLevel(CommandSender commandSender, String args[]) {
-
- int mobLevel = 0;
-
- if (commandSender instanceof Player) {
-
- try {
-
- mobLevel = Integer.valueOf(args[2]);
-
- } catch (Error error) {
-
- commandSender.sendMessage("Error assigning mob level to Elite Mob. Mob level must be above 0.");
-
- }
-
-
- } else if (commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender) {
-
- try {
-
- mobLevel = Integer.valueOf(args[6]);
-
- } catch (Error error) {
-
- commandSender.sendMessage("Error assigning mob level to Elite Mob. Mob level must be above 0.");
-
- }
-
- }
-
- if (mobLevel < 1)
- mobLevel = 1;
-
- return mobLevel;
-
- }
-
- private static HashSet getPowers(CommandSender commandSender, String args[]) {
-
- ArrayList mobPowers = new ArrayList();
-
- if (commandSender instanceof Player) {
-
- if (args.length > 3) {
-
- int index = 0;
-
- for (String arg : args) {
-
- //mob powers start after arg 2
- if (index > 2)
- mobPowers.add(arg);
-
- index++;
-
- }
-
- }
-
- } else if (commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender) {
-
- if (args.length > 6) {
-
- int index = 0;
-
- for (String arg : args) {
-
- //mob powers start after arg 6
- if (index > 6)
- mobPowers.add(arg);
-
- index++;
-
- }
-
- }
-
- }
-
- return getPowers(mobPowers, commandSender);
-
- }
-
- private static HashSet getPowers(ArrayList mobPowers, CommandSender commandSender) {
-
- HashSet elitePowers = new HashSet<>();
-
- if (mobPowers.size() > 0) {
-
- for (String string : mobPowers) {
-
- switch (string.toLowerCase()) {
- //major powers
- case "zombiefriends":
- elitePowers.add(new ZombieFriends());
- break;
- case "zombienecronomicon":
- elitePowers.add(new ZombieNecronomicon());
- break;
- case "zombieteamrocket":
- elitePowers.add(new ZombieTeamRocket());
- break;
- case "zombieparents":
- elitePowers.add(new ZombieParents());
- break;
- case "zombiebloat":
- elitePowers.add(new ZombieBloat());
- break;
- case "skeletontrackingarrow":
- elitePowers.add(new SkeletonTrackingArrow());
- break;
- case "skeletonpillar":
- elitePowers.add(new SkeletonPillar());
- break;
- //minor powers
- case "attackarrow":
- elitePowers.add(new AttackArrow());
- break;
- case "attackblinding":
- elitePowers.add(new AttackBlinding());
- break;
- case "attackconfusing":
- elitePowers.add(new AttackConfusing());
- break;
- case "attackfire":
- elitePowers.add(new AttackConfusing());
- break;
- case "attackfireball":
- elitePowers.add(new AttackFireball());
- break;
- case "attackfreeze":
- elitePowers.add(new AttackFreeze());
- break;
- case "attackgravity":
- elitePowers.add(new AttackGravity());
- break;
- case "attackpoison":
- elitePowers.add(new AttackPoison());
- break;
- case "attackpush":
- elitePowers.add(new AttackPush());
- break;
- case "attackweakness":
- elitePowers.add(new AttackWeakness());
- break;
- case "attackweb":
- elitePowers.add(new AttackWeb());
- break;
- case "attackwither":
- elitePowers.add(new AttackWither());
- break;
- case "bonusloot":
- elitePowers.add(new BonusLoot());
- break;
- case "invisibility":
- elitePowers.add(new Invisibility());
- break;
- case "invulnerabilityarrow":
- elitePowers.add(new InvulnerabilityArrow());
- break;
- case "invulnerabilityfalldamage":
- elitePowers.add(new InvulnerabilityFallDamage());
- break;
- case "invulnerabilityfire":
- elitePowers.add(new InvulnerabilityFire());
- break;
- case "invulnerabilityknockback":
- elitePowers.add(new InvulnerabilityKnockback());
- break;
- case "movementspeed":
- elitePowers.add(new MovementSpeed());
- break;
- case "taunt":
- elitePowers.add(new Taunt());
- break;
- default:
- commandSender.sendMessage(string + " is not a valid power.");
- commandSender.sendMessage("Valid powers: attackarrow, attackblinding, attackconfusing," +
- " attackfire, attackfireball, attackfreeze,attackgravity, attackpoison, attackpush, " +
- "attackweakness, attackweb, attackwither, bonusloot, invisibility, invulnerabilityarrow," +
- "invulnerabilityfalldamage, invulnerabilityfire, invulnerabilityknockback, movementspeed," +
- "taunt, zombiefriends, zombienecronomicon, zombieteamrocket, zombieteamrocket, zombieparents," +
- "zombiebloat, skeletontrackingarrow, skeletonpillar");
- break;
-
- }
-
- }
-
- }
-
- return elitePowers;
-
- }
-
- private static void spawnSuperMob(EntityType entityType, Location location) {
- SuperMobConstructor.constructSuperMob((LivingEntity) location.getWorld().spawnEntity(location, entityType));
- }
-
- public static void spawnBossMob(Player player, String[] args) {
-
- Location cursorLocation = player.getTargetBlock(null, 5).getLocation().add(new Vector(0.5, 2, 0.5));
-
- if (args[1].equalsIgnoreCase("treasuregoblin")) {
-
- TreasureGoblin.createGoblin(cursorLocation);
- player.sendMessage("Spawned treasure goblin");
-
- }
-
- if (args[1].equalsIgnoreCase("zombieking")) {
-
- ZombieKing.spawnZombieKing(cursorLocation);
- player.sendMessage("Spawned zombie king");
-
- }
-
- if (args[1].equalsIgnoreCase("kraken")) {
-
- Squid squid = (Squid) cursorLocation.getWorld().spawnEntity(cursorLocation, EntityType.SQUID);
- Kraken.spawnKraken(squid.getLocation());
- squid.remove();
- player.sendMessage("Spawned Kraken");
-
- }
-
- if (args[1].equalsIgnoreCase("balrog")) {
-
- Balrog.spawnBalrog(cursorLocation);
- player.sendMessage("Spawned Balrog");
-
- }
-
- if (args[1].equalsIgnoreCase("fae")) {
-
- Fae.spawnFae(cursorLocation);
- player.sendMessage("Spawned Fae");
-
- }
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/StatsCommandHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/StatsCommandHandler.java
deleted file mode 100644
index 639fc0d2f..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/StatsCommandHandler.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.EntityTracker;
-import com.magmaguy.elitemobs.MetadataHandler;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.DefaultConfig;
-import org.bukkit.Bukkit;
-import org.bukkit.World;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.entity.LivingEntity;
-import org.bukkit.entity.Player;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import static com.magmaguy.elitemobs.EliteMobs.validWorldList;
-import static org.bukkit.Bukkit.getLogger;
-import static org.bukkit.Bukkit.getServer;
-
-/**
- * Created by MagmaGuy on 01/05/2017.
- */
-public class StatsCommandHandler {
-
- public static void statsHandler(CommandSender commandSender) {
-
- int mobLevelSavingsCount = 0;
- int totalMobCount = 0;
- int aggressiveCount = 0;
- int passiveCount = 0;
- int blazeCount = 0;
- int caveSpiderCount = 0;
- int creeperCount = 0;
- int endermanCount = 0;
- int endermiteCount = 0;
- int huskCount = 0;
- int ironGolemCount = 0;
- int pigZombieCount = 0;
- int polarBearCount = 0;
- int silverfishCount = 0;
- int skeletonCount = 0;
- int spiderCount = 0;
- int strayCount = 0;
- int witchCount = 0;
- int witherSkeletonCount = 0;
- int zombieCount = 0;
- int zombieVillagerCount = 0;
-
- int chickenCount = 0;
- int cowCount = 0;
- int mushroomCowCount = 0;
- int pigCount = 0;
- int sheepCount = 0;
-
- for (World world : validWorldList) {
-
- for (LivingEntity livingEntity : world.getLivingEntities()) {
-
- if (EntityTracker.isEliteMob(livingEntity) ||
- EntityTracker.isSuperMob(livingEntity)) {
-
- totalMobCount++;
-
- if (EntityTracker.isEliteMob(livingEntity)) {
-
- mobLevelSavingsCount += EntityTracker.getEliteMobEntity(livingEntity).getLevel();
- aggressiveCount++;
-
- switch (livingEntity.getType()) {
-
- case ZOMBIE:
- zombieCount++;
- break;
- case HUSK:
- huskCount++;
- break;
- case ZOMBIE_VILLAGER:
- zombieVillagerCount++;
- break;
- case SKELETON:
- skeletonCount++;
- break;
- case WITHER_SKELETON:
- witherSkeletonCount++;
- break;
- case STRAY:
- strayCount++;
- break;
- case PIG_ZOMBIE:
- pigZombieCount++;
- break;
- case CREEPER:
- creeperCount++;
- break;
- case SPIDER:
- spiderCount++;
- break;
- case ENDERMAN:
- endermanCount++;
- break;
- case CAVE_SPIDER:
- caveSpiderCount++;
- break;
- case SILVERFISH:
- silverfishCount++;
- break;
- case BLAZE:
- blazeCount++;
- break;
- case WITCH:
- witchCount++;
- break;
- case ENDERMITE:
- endermiteCount++;
- break;
- case POLAR_BEAR:
- polarBearCount++;
- break;
- case IRON_GOLEM:
- ironGolemCount++;
- break;
- default:
- getLogger().info("Error: Couldn't assign custom mob name due to unexpected aggressive boss mob (talk to the dev!)");
- getLogger().info("Missing mob type: " + livingEntity.getType());
- break;
- }
-
-
- } else if (EntityTracker.isSuperMob(livingEntity)) {
-
- //passive EliteMobs only stack at 50 right now
- //TODO: redo this count at some other stage of this plugin's development
- mobLevelSavingsCount += ConfigValues.defaultConfig.getInt(DefaultConfig.SUPERMOB_STACK_AMOUNT);
- passiveCount++;
-
- switch (livingEntity.getType()) {
-
- case CHICKEN:
- chickenCount++;
- break;
- case COW:
- cowCount++;
- break;
- case MUSHROOM_COW:
- mushroomCowCount++;
- break;
- case PIG:
- pigCount++;
- break;
- case SHEEP:
- sheepCount++;
- break;
- default:
- getLogger().info("Error: Couldn't assign custom mob name due to unexpected passive boss mob (talk to the dev!)");
- getLogger().info("Missing mob type: " + livingEntity.getType());
- break;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- if (commandSender instanceof Player) {
-
- Player player = (Player) commandSender;
-
- player.sendMessage("§5§m-----------------------------------------------------");
- player.sendMessage("§a§lEliteMobs v. " + Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS).getDescription().getVersion() + " stats:");
- player.sendMessage("There are currently §l§6" + totalMobCount + " §f§rEliteMobs replacing §l§e" +
- mobLevelSavingsCount + " §f§rregular mobs.");
-
- if (aggressiveCount > 0) {
-
- String aggressiveCountMessage = "§c" + aggressiveCount + " §4Aggressive EliteMobs: §f";
-
- HashMap unsortedMobCount = new HashMap();
-
- unsortedMobCountFilter(unsortedMobCount, blazeCount, "blazes");
- unsortedMobCountFilter(unsortedMobCount, caveSpiderCount, "cave spiders");
- unsortedMobCountFilter(unsortedMobCount, creeperCount, "creepers");
- unsortedMobCountFilter(unsortedMobCount, endermanCount, "endermen");
- unsortedMobCountFilter(unsortedMobCount, endermiteCount, "endermites");
- unsortedMobCountFilter(unsortedMobCount, huskCount, "husks");
- unsortedMobCountFilter(unsortedMobCount, pigZombieCount, "zombiepigmen");
- unsortedMobCountFilter(unsortedMobCount, polarBearCount, "polar bears");
- unsortedMobCountFilter(unsortedMobCount, silverfishCount, "silverfish");
- unsortedMobCountFilter(unsortedMobCount, skeletonCount, "skeletons");
- unsortedMobCountFilter(unsortedMobCount, spiderCount, "spiders");
- unsortedMobCountFilter(unsortedMobCount, strayCount, "strays");
- unsortedMobCountFilter(unsortedMobCount, witchCount, "witches");
- unsortedMobCountFilter(unsortedMobCount, witherSkeletonCount, "wither skeletons");
- unsortedMobCountFilter(unsortedMobCount, zombieCount, "zombie");
- unsortedMobCountFilter(unsortedMobCount, zombieVillagerCount, "zombie villagers");
-
- player.sendMessage(messageStringAppender(aggressiveCountMessage, unsortedMobCount));
-
- }
-
- if (passiveCount > 0) {
-
- String passiveCountMessage = "§b" + passiveCount + " §3Passive EliteMobs: §f";
-
- HashMap unsortedMobCount = new HashMap();
-
- unsortedMobCountFilter(unsortedMobCount, chickenCount, "chickens");
- unsortedMobCountFilter(unsortedMobCount, cowCount, "cows");
- unsortedMobCountFilter(unsortedMobCount, ironGolemCount, "iron golems");
- unsortedMobCountFilter(unsortedMobCount, mushroomCowCount, "mushroom cows");
- unsortedMobCountFilter(unsortedMobCount, pigCount, "pigs");
- unsortedMobCountFilter(unsortedMobCount, sheepCount, "sheep");
-
- player.sendMessage(messageStringAppender(passiveCountMessage, unsortedMobCount));
-
- }
-
- player.sendMessage("§5§m-----------------------------------------------------");
-
- } else if (commandSender instanceof ConsoleCommandSender) {
-
- getServer().getConsoleSender().sendMessage("§5§m-------------------------------------------------------------");
- getServer().getConsoleSender().sendMessage("§a§lEliteMobs stats:");
- getServer().getConsoleSender().sendMessage("There are currently §l§6" + totalMobCount + " §f§rEliteMobs replacing §l§e" +
- mobLevelSavingsCount + " §f§rregular mobs.");
-
- if (aggressiveCount > 0) {
-
- String aggressiveCountMessage = "§c" + aggressiveCount + " §4Aggressive EliteMobs: §f";
-
- HashMap unsortedMobCount = new HashMap();
-
- unsortedMobCountFilter(unsortedMobCount, blazeCount, "blazes");
- unsortedMobCountFilter(unsortedMobCount, caveSpiderCount, "cave spiders");
- unsortedMobCountFilter(unsortedMobCount, creeperCount, "creepers");
- unsortedMobCountFilter(unsortedMobCount, endermanCount, "endermen");
- unsortedMobCountFilter(unsortedMobCount, endermiteCount, "endermites");
- unsortedMobCountFilter(unsortedMobCount, huskCount, "husks");
- unsortedMobCountFilter(unsortedMobCount, ironGolemCount, "iron golems");
- unsortedMobCountFilter(unsortedMobCount, pigZombieCount, "zombiepigmen");
- unsortedMobCountFilter(unsortedMobCount, polarBearCount, "polar bears");
- unsortedMobCountFilter(unsortedMobCount, silverfishCount, "silverfish");
- unsortedMobCountFilter(unsortedMobCount, skeletonCount, "skeletons");
- unsortedMobCountFilter(unsortedMobCount, spiderCount, "spiders");
- unsortedMobCountFilter(unsortedMobCount, strayCount, "strays");
- unsortedMobCountFilter(unsortedMobCount, witchCount, "witches");
- unsortedMobCountFilter(unsortedMobCount, witherSkeletonCount, "wither skeletons");
- unsortedMobCountFilter(unsortedMobCount, zombieCount, "zombie");
- unsortedMobCountFilter(unsortedMobCount, zombieVillagerCount, "zombie villagers");
-
- getServer().getConsoleSender().sendMessage(messageStringAppender(aggressiveCountMessage, unsortedMobCount));
-
- }
-
- if (passiveCount > 0) {
-
- String passiveCountMessage = "§b" + passiveCount + " §3Passive EliteMobs: §f";
-
- HashMap unsortedMobCount = new HashMap();
-
- unsortedMobCountFilter(unsortedMobCount, chickenCount, "chickens");
- unsortedMobCountFilter(unsortedMobCount, cowCount, "cows");
- unsortedMobCountFilter(unsortedMobCount, mushroomCowCount, "mushroom cows");
- unsortedMobCountFilter(unsortedMobCount, pigCount, "pigs");
- unsortedMobCountFilter(unsortedMobCount, sheepCount, "sheep");
-
- getServer().getConsoleSender().sendMessage(messageStringAppender(passiveCountMessage, unsortedMobCount));
-
- }
-
- getServer().getConsoleSender().sendMessage("§5§m-------------------------------------------------------------");
-
- }
-
- }
-
- private static void unsortedMobCountFilter(HashMap unsortedMobCount, int count, String mobTypeName) {
-
- if (count > 0) {
-
- unsortedMobCount.put(mobTypeName, count);
-
- }
-
- }
-
- private static String messageStringAppender(String countMessage, HashMap unsortedMobCount) {
-
- Iterator iterator = unsortedMobCount.entrySet().iterator();
-
- while (iterator.hasNext()) {
-
- Map.Entry pair = (Map.Entry) iterator.next();
-
- String mobCountString = "§6§l" + pair.getValue();
- String commaString = ",";
- String spacing = " ";
- String mobNameString = "§r§f" + pair.getKey();
-
- countMessage += commaString + spacing + mobCountString + spacing + mobNameString;
-
- }
-
- return countMessage;
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/TreasureChestCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/TreasureChestCommands.java
new file mode 100644
index 000000000..a0204b75a
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/TreasureChestCommands.java
@@ -0,0 +1,18 @@
+package com.magmaguy.elitemobs.commands;
+
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import org.bukkit.entity.Player;
+
+public class TreasureChestCommands {
+ private TreasureChestCommands() {
+ }
+
+ public static void addRelativeTreasureChest(Player player, String treasureChestFilename, String minidungeonName) {
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonName);
+ if (minidungeon == null) {
+ player.sendMessage("Invalid minidungeon name!");
+ return;
+ }
+ minidungeon.addRelativeTreasureChest(treasureChestFilename, player.getLocation().getBlock().getLocation(), player);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/TriggerEventHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/TriggerEventHandler.java
deleted file mode 100644
index 53218c106..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/TriggerEventHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.magmaguy.elitemobs.commands;
-
-import com.magmaguy.elitemobs.events.DeadMoon;
-import com.magmaguy.elitemobs.events.SmallTreasureGoblin;
-import org.bukkit.command.CommandSender;
-
-public class TriggerEventHandler {
-
- public static void triggerEventCommand(CommandSender commandSender, String[] args){
-
- if (CommandHandler.permCheck(CommandHandler.EVENT_LAUNCH_SMALLTREASUREGOBLIN, commandSender) && args[1].equalsIgnoreCase("smalltreasuregoblin")) {
- SmallTreasureGoblin.initializeEvent();
- commandSender.sendMessage("Queued small treasure goblin event for next valid zombie spawn");
- }
- if (CommandHandler.permCheck(CommandHandler.EVENT_LAUNCH_DEADMOON, commandSender) && args[1].equalsIgnoreCase("deadmoon")) {
- DeadMoon.initializeEvent();
- commandSender.sendMessage("Queued deadmoon event for next new moon");
- }
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/UserCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/UserCommands.java
new file mode 100644
index 000000000..fab55a27d
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/UserCommands.java
@@ -0,0 +1,374 @@
+package com.magmaguy.elitemobs.commands;
+
+import cloud.commandframework.ArgumentDescription;
+import cloud.commandframework.Command;
+import cloud.commandframework.arguments.CommandArgument;
+import cloud.commandframework.arguments.standard.DoubleArgument;
+import cloud.commandframework.arguments.standard.StringArgument;
+import cloud.commandframework.bukkit.BukkitCommandManager;
+import cloud.commandframework.extra.confirmation.CommandConfirmationManager;
+import cloud.commandframework.meta.CommandMeta;
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.api.PlayerPreTeleportEvent;
+import com.magmaguy.elitemobs.commands.admin.CheckTierOthersCommand;
+import com.magmaguy.elitemobs.commands.combat.CheckTierCommand;
+import com.magmaguy.elitemobs.commands.guild.AdventurersGuildCommand;
+import com.magmaguy.elitemobs.commands.quests.QuestCommand;
+import com.magmaguy.elitemobs.config.DefaultConfig;
+import com.magmaguy.elitemobs.config.EconomySettingsConfig;
+import com.magmaguy.elitemobs.config.TranslationConfig;
+import com.magmaguy.elitemobs.instanced.MatchInstance;
+import com.magmaguy.elitemobs.items.EliteItemLore;
+import com.magmaguy.elitemobs.items.ShareItem;
+import com.magmaguy.elitemobs.menus.*;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.playerdata.statusscreen.PlayerStatusScreen;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public class UserCommands {
+
+ public UserCommands(BukkitCommandManager manager, Command.Builder builder) {
+ // /em adventurersguild
+ manager.command(builder.literal("adventurersguild", "ag")
+ .meta(CommandMeta.DESCRIPTION, "Teleports players to the Adventurer's Guild Hub or opens the Adventurer's Guild menu.")
+ .senderType(Player.class)
+ .permission("elitemobs.adventurersguild.command")
+ //permission is dealt inside of the command
+ .handler(commandContext -> {
+ AdventurersGuildCommand.adventurersGuildCommand((Player) commandContext.getSender());
+ }));
+
+ // /em shareitem
+ manager.command(builder.literal("shareitem")
+ .meta(CommandMeta.DESCRIPTION, "Shares a held Elite item on chat")
+ .senderType(Player.class)
+ .permission("elitemobs.shareitem")
+ .handler(commandContext -> ShareItem.showOnChat((Player) commandContext.getSender())));
+
+ // /em shop
+ manager.command(builder.literal("shop")
+ .meta(CommandMeta.DESCRIPTION, "Opens the procedurally generated item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.shop.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender()))
+ ProceduralShopMenu.shopInitializer((Player) commandContext.getSender());
+ }));
+
+ // /em customshop
+ manager.command(builder.literal("customshop")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.customshop.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender()))
+ CustomShopMenu.customShopInitializer((Player) commandContext.getSender());
+ }));
+
+ // /em repair
+ manager.command(builder.literal("repair")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.repair.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ RepairMenu repairMenu = new RepairMenu();
+ repairMenu.constructRepairMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em enhance
+ manager.command(builder.literal("enhance")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.enhancer.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ EnhancementMenu enhancementMenu = new EnhancementMenu();
+ enhancementMenu.constructEnhancementMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em refine
+ manager.command(builder.literal("refine")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.refiner.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ RefinerMenu refinerMenu = new RefinerMenu();
+ refinerMenu.constructRefinerMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em smelt
+ manager.command(builder.literal("smelt")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.smelt.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ SmeltMenu smeltMenu = new SmeltMenu();
+ smeltMenu.constructSmeltMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em scrap
+ manager.command(builder.literal("scrap")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.scrap.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ ScrapperMenu scrapperMenu = new ScrapperMenu();
+ scrapperMenu.constructScrapMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em unbind
+ manager.command(builder.literal("unbind")
+ .meta(CommandMeta.DESCRIPTION, "Opens the custom item shop or teleports the player to the Adventurer's Guild Hub")
+ .senderType(Player.class)
+ .permission("elitemobs.unbind.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender())) {
+ UnbindMenu unbindMenu = new UnbindMenu();
+ unbindMenu.constructUnbinderMenu((Player) commandContext.getSender());
+ }
+ }));
+
+ // /em wallet
+ manager.command(builder.literal("wallet")
+ .meta(CommandMeta.DESCRIPTION, "Checks the EliteMobs currency")
+ .senderType(Player.class)
+ .permission("elitemobs.currency.check")
+ .handler(commandContext -> {
+ if (DefaultConfig.isOtherCommandsLeadToEMStatusMenu())
+ new PlayerStatusScreen((Player) commandContext.getSender());
+ else
+ CurrencyCommandsHandler.walletCommand((Player) commandContext.getSender());
+ }));
+
+ // /em quest accept
+ manager.command(builder.literal("quest")
+ .literal("accept")
+ .argument(StringArgument.newBuilder("questID"), ArgumentDescription.of("Quest ID"))
+ .meta(CommandMeta.DESCRIPTION, "Accepts a quest")
+ .senderType(Player.class)
+ .permission("elitemobs.quest.command")
+ .handler(commandContext -> {
+ QuestCommand.joinQuest(commandContext.get("questID"), (Player) commandContext.getSender());
+ }));
+
+ // /em quest track
+ manager.command(builder.literal("quest")
+ .literal("track")
+ .argument(StringArgument.newBuilder("questID"), ArgumentDescription.of("Quest ID"))
+ .meta(CommandMeta.DESCRIPTION, "Toggles quest tracking")
+ .senderType(Player.class)
+ .permission("elitemobs.quest.command")
+ .handler(commandContext -> {
+ QuestCommand.trackQuest(commandContext.get("questID"), (Player) commandContext.getSender());
+ }));
+
+ // /em quest complete
+ manager.command(builder.literal("quest")
+ .literal("complete")
+ .argument(StringArgument.newBuilder("questID"), ArgumentDescription.of("Quest ID"))
+ .meta(CommandMeta.DESCRIPTION, "Completes a quest")
+ .senderType(Player.class)
+ .permission("elitemobs.quest.command")
+ .handler(commandContext -> {
+ QuestCommand.completeQuest(commandContext.get("questID"), (Player) commandContext.getSender());
+ }));
+
+
+ // /em quest leave
+ manager.command(builder.literal("quest")
+ .literal("leave")
+ .argument(StringArgument.newBuilder("questID"), ArgumentDescription.of("Quest ID"))
+ .meta(CommandMeta.DESCRIPTION, "Leaves a quest")
+ .senderType(Player.class)
+ .permission("elitemobs.quest.command")
+ .handler(commandContext -> QuestCommand.leaveQuest((Player) commandContext.getSender(), commandContext.get("questID"))));
+
+ CommandArgument onlinePlayers = StringArgument.newBuilder("onlinePlayer")
+ .withSuggestionsProvider(((objectCommandContext, s) -> {
+ ArrayList arrayList = new ArrayList<>();
+ Bukkit.getOnlinePlayers().forEach(player -> arrayList.add(player.getName()));
+ return arrayList;
+ })).build();
+
+
+ // Create the confirmation manager. This allows us to require certain commands to be
+ // confirmed before they can be executed
+ CommandConfirmationManager paymentConfirmationManager = new CommandConfirmationManager<>(
+ /* Timeout */ 30L,
+ /* Timeout unit */ TimeUnit.SECONDS,
+ /* Action when confirmation is required */ context -> context.getCommandContext().getSender().sendMessage(
+ ChatColorConverter.convert(TranslationConfig.getEconomyTaxMessage()
+ .replace("$command", "/em confirm")
+ .replace("$percentage", (EconomySettingsConfig.getPlayerToPlayerTaxes() * 100) + ""))),
+ /* Action when no confirmation is pending */ sender -> sender.sendMessage(
+ ChatColorConverter.convert(TranslationConfig.getNoPendingCommands()))
+ );
+
+ // Register the confirmation processor. This will enable confirmations for commands that require it
+ paymentConfirmationManager.registerConfirmationProcessor(manager);
+
+ // Add a confirmation command
+ manager.command(builder.literal("confirm")
+ .meta(CommandMeta.DESCRIPTION, "Confirm a pending command")
+ .handler(paymentConfirmationManager.createConfirmationExecutionHandler()));
+
+ // /em pay
+ manager.command(builder.literal("pay")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .argument(DoubleArgument.newBuilder("amount"), ArgumentDescription.of("Amount to pay"))
+ .meta(CommandMeta.DESCRIPTION, "Pays an amount of currency to another player")
+ .meta(CommandConfirmationManager.META_CONFIRMATION_REQUIRED, true)
+ .senderType(Player.class)
+ .permission("elitemobs.currency.pay")
+ .handler(commandContext -> {
+ paymentConfirmationManager.createConfirmationExecutionHandler();
+ CurrencyCommandsHandler.payCommand(
+ (Player) commandContext.getSender(),
+ commandContext.get("onlinePlayer"),
+ commandContext.get("amount"));
+ }));
+
+
+ // /em rank
+ manager.command(builder.literal("rank")
+ .meta(CommandMeta.DESCRIPTION, "Opens the EliteMobs rank menu.")
+ .senderType(Player.class)
+ .permission("elitemobs.rank.command")
+ .handler(commandContext -> {
+ if (!AdventurersGuildCommand.adventurersGuildTeleport((Player) commandContext.getSender()))
+ AdventurersGuildCommand.adventurersGuildCommand((Player) commandContext.getSender());
+ }));
+
+ // /em menu
+ manager.command(builder.literal("menu")
+ .meta(CommandMeta.DESCRIPTION, "Opens the EliteMobs status screen.")
+ .senderType(Player.class)
+ .handler(commandContext -> new PlayerStatusScreen((Player) commandContext.getSender())));
+
+ // /em rank
+ manager.command(builder.literal("checktier")
+ .meta(CommandMeta.DESCRIPTION, "Checks your equipped EliteMobs gear tier.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ if (DefaultConfig.isOtherCommandsLeadToEMStatusMenu())
+ new PlayerStatusScreen((Player) commandContext.getSender());
+ else new CheckTierCommand((Player) commandContext.getSender());
+ }));
+
+ // /em checktier
+ manager.command(builder.literal("checktier")
+ .argument(onlinePlayers.copy(), ArgumentDescription.of("Player name"))
+ .meta(CommandMeta.DESCRIPTION, "Checks the equipped EliteMobs gear tier of another player.")
+ .senderType(CommandSender.class)
+ .permission("elitemobs.checktier.others")
+ .handler(commandContext -> new CheckTierOthersCommand(commandContext.getSender(), commandContext.get("onlinePlayer"))));
+
+ // /em trackcustomboss uuid
+ manager.command(builder.literal("trackcustomboss")
+ .argument(StringArgument.newBuilder("uuid"), ArgumentDescription.of("UUID of the custom boss to track."))
+ .meta(CommandMeta.DESCRIPTION, "Tracks a Custom Boss.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ try {
+ for (CustomBossEntity customBossEntity : CustomBossEntity.getTrackableCustomBosses())
+ if (customBossEntity.getEliteUUID().equals(UUID.fromString(commandContext.get("uuid")))) {
+ customBossEntity.getCustomBossBossBar().addTrackingPlayer((Player) commandContext.getSender());
+ return;
+ }
+ commandContext.getSender().sendMessage("[EliteMobs] Sorry, this boss is already gone!");
+ } catch (Exception ex) {
+ //happens when players try to track an entity that has despawned for any reason
+ commandContext.getSender().sendMessage("[EliteMobs] Sorry, this boss is already gone!");
+ }
+ }));
+
+ // /em updateitem
+ manager.command(builder.literal("updateitem")
+ .meta(CommandMeta.DESCRIPTION, "Manually updates the lore of an item. Used for debugging purposes.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ new EliteItemLore(((Player) commandContext.getSender()).getItemInHand(), false);
+ }));
+
+ // /em dungeontp
+ manager.command(builder.literal("dungeontp")
+ .argument(StringArgument.newBuilder("dungeonid"), ArgumentDescription.of("ID of the dungeon to teleport to."))
+ .meta(CommandMeta.DESCRIPTION, "Teleports players to Lairs, Minidungeons and Dungeons.")
+ .permission("elitemobs.dungeontp")
+ .senderType(Player.class)
+ .handler(commandContext -> DungeonCommands.teleport((Player) commandContext.getSender(), commandContext.get("dungeonid"))));
+
+ // /em spawntp
+ manager.command(builder.literal("spawntp")
+ .meta(CommandMeta.DESCRIPTION, "Teleports players to the server spawn.")
+ .senderType(Player.class)
+ .permission("elitemobs.spawntp")
+ .handler(commandContext -> {
+ if (DefaultConfig.getDefaultSpawnLocation() != null)
+ PlayerPreTeleportEvent.teleportPlayer((Player) commandContext.getSender(), DefaultConfig.getDefaultSpawnLocation());
+ }));
+
+ // /em alt
+ manager.command(builder.literal("alt")
+ .meta(CommandMeta.DESCRIPTION, "Changes the style of the /em menu.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ PlayerData.setUseBookMenus(((Player) commandContext.getSender()), !PlayerData.getUseBookMenus(((Player) commandContext.getSender()).getUniqueId()));
+ commandContext.getSender().sendMessage(TranslationConfig.getSwitchEMStyleMessage());
+ }));
+
+ // /em dismiss
+ manager.command(builder.literal("dismiss")
+ .meta(CommandMeta.DESCRIPTION, "Dismisses /em menu message.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ PlayerData.setDismissEMStatusScreenMessage(((Player) commandContext.getSender()), !PlayerData.getDismissEMStatusScreenMessage(((Player) commandContext.getSender()).getUniqueId()));
+ }));
+
+ // /em arena
+ manager.command(builder.literal("arena")
+ .meta(CommandMeta.DESCRIPTION, "Opens the arena menu.")
+ .argument(StringArgument.newBuilder("dungeonid"), ArgumentDescription.of("Name of the arena to go to."))
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ ArenaCommands.openArenaMenu(((Player) commandContext.getSender()), commandContext.get("arena"));
+ }));
+
+ // /em start - this is for instanced content
+ manager.command(builder.literal("start")
+ .meta(CommandMeta.DESCRIPTION, "When in instanced content, starts the countdown to start doing the content.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ MatchInstance matchInstance = MatchInstance.getPlayerInstance(((Player) commandContext.getSender()));
+ if (matchInstance != null)
+ matchInstance.countdownMatch();
+ }));
+
+ // /em quit - this is for instanced content
+ manager.command(builder.literal("quit")
+ .meta(CommandMeta.DESCRIPTION, "When in instanced content, makes the player leave the instance.")
+ .senderType(Player.class)
+ .handler(commandContext -> {
+ MatchInstance matchInstance = MatchInstance.getAnyPlayerInstance(((Player) commandContext.getSender()));
+ if (matchInstance != null)
+ matchInstance.removeAnyKind((Player) commandContext.getSender());
+ }));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/CheckTierOthersCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/CheckTierOthersCommand.java
new file mode 100644
index 000000000..60bcfaae4
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/CheckTierOthersCommand.java
@@ -0,0 +1,35 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.config.commands.premade.CheckTierOthersConfig;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class CheckTierOthersCommand {
+
+ public CheckTierOthersCommand(CommandSender commandSender, String playerName) {
+
+ Player player = Bukkit.getPlayer(playerName);
+ if (player == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Invalid player name!"));
+ return;
+ }
+
+ double gearTier = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getFullPlayerTier(true);
+ double guildRank = GuildRank.getActiveGuildRank(player);
+ if (guildRank == 0)
+ guildRank = -10;
+ else
+ guildRank--;
+ guildRank = (guildRank * 0.2);
+
+ commandSender.sendMessage(CheckTierOthersConfig.message1.replace("$player", player.getDisplayName()).replace("$tier", gearTier + ""));
+ commandSender.sendMessage(CheckTierOthersConfig.message2.replace("$player", player.getDisplayName()).replace("$tier", guildRank + ""));
+ commandSender.sendMessage(CheckTierOthersConfig.message3.replace("$player", player.getDisplayName()).replace("$tier", (gearTier + guildRank) + ""));
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/DebugScreen.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/DebugScreen.java
new file mode 100644
index 000000000..7bd3986c8
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/DebugScreen.java
@@ -0,0 +1,84 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.RegionalBossEntity;
+import com.magmaguy.elitemobs.playerdata.statusscreen.PlayerStatusScreen;
+import com.magmaguy.elitemobs.utils.BookMaker;
+import com.magmaguy.elitemobs.utils.SpigotMessage;
+import net.md_5.bungee.api.chat.TextComponent;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+public class DebugScreen {
+
+ public static void open(Player player, String argument) {
+ if (Bukkit.getPlayer(argument) != null)
+ new PlayerStatusScreen(player, Bukkit.getPlayer(argument));
+ else openBossScreen(player, argument);
+ }
+
+ private static void openBossScreen(Player player, String argument) {
+
+ TextComponent[] pages = new TextComponent[100];
+
+ int counter = 0;
+ for (EliteEntity eliteEntity : EntityTracker.getEliteMobEntities().values())
+ if (!(eliteEntity instanceof RegionalBossEntity))
+ if (eliteEntity instanceof CustomBossEntity) {
+ TextComponent textComponent = generateEntry((CustomBossEntity) eliteEntity, argument, player);
+ if (textComponent == null) continue;
+ pages[counter] = textComponent;
+ counter++;
+ }
+
+ for (RegionalBossEntity regionalBossEntity : RegionalBossEntity.getRegionalBossEntities()) {
+ TextComponent textComponent = generateEntry(regionalBossEntity, argument, player);
+ if (textComponent == null) continue;
+ pages[counter] = textComponent;
+ counter++;
+ }
+
+ BookMaker.generateBook(player, pages);
+
+ }
+
+ private static TextComponent generateEntry(CustomBossEntity customBossEntity, String argument, Player player) {
+ if (!customBossEntity.getCustomBossesConfigFields().getFilename().contains(argument) &&
+ !customBossEntity.getCustomBossesConfigFields().getName().toLowerCase().contains(argument.toLowerCase()))
+ return null;
+ TextComponent page = new TextComponent();
+ page.addExtra(customBossEntity.getCustomBossesConfigFields().getFilename() + "\n");
+ page.addExtra("Name: " + ChatColorConverter.convert(customBossEntity.getCustomBossesConfigFields().getName()) + ChatColor.BLACK + "\n");
+ page.addExtra("Level: " + customBossEntity.getCustomBossesConfigFields().getLevel() + "\n");
+ if (customBossEntity.getLivingEntity() != null) {
+ page.addExtra("Is Alive (MC): " + !customBossEntity.getLivingEntity().isDead() + "\n");
+ page.addExtra(SpigotMessage.commandHoverMessage(ChatColor.BLUE + "XYZ: " + "\n",
+ customBossEntity.getLocation().getBlockX() + ", " +
+ customBossEntity.getLocation().getBlockY() + ", " +
+ customBossEntity.getLocation().getBlockZ() + "\n" +
+ ChatColor.BLUE + "Click to teleport! (if alive)",
+ "/em debugtp " + customBossEntity.getEliteUUID().toString()));
+ page.addExtra("Has AI: " + !customBossEntity.getLivingEntity().hasAI() + "\n");
+ } else
+ page.addExtra("Is Alive (MC): false\n");
+ if (customBossEntity.getLocation() != null && player.getWorld().equals(customBossEntity.getLocation().getWorld()))
+ page.addExtra(SpigotMessage.hoverMessage(ChatColor.BLUE + "Spawn distance",
+ "Spawn distance: X=" + (int) (player.getLocation().getX() - customBossEntity.getSpawnLocation().getX())
+ + " | Y=" + (int) (player.getLocation().getY() - customBossEntity.getSpawnLocation().getY()) +
+ " | Z=" + (int) (player.getLocation().getZ() - customBossEntity.getSpawnLocation().getZ()) + "\n"));
+ page.addExtra("Is Persistent: " + customBossEntity.getCustomBossesConfigFields().isPersistent() + "\n");
+ if (customBossEntity instanceof RegionalBossEntity) {
+ page.addExtra("Is Respawning: " + ((RegionalBossEntity) customBossEntity).isRespawning() + "\n");
+ }
+
+ page.addExtra(SpigotMessage.commandHoverMessage(ChatColor.BLUE + "Boss trace!",
+ "Remember, it requires debug mode to be on! This is used for advanced debugging, ask on discord if you want to know more about it.",
+ "/elitemobs trace " + customBossEntity.getEliteUUID().toString()));
+ return page;
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/EventCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/EventCommand.java
new file mode 100644
index 000000000..e0301dcb7
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/EventCommand.java
@@ -0,0 +1,20 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.events.TimedEvent;
+import org.bukkit.command.CommandSender;
+
+public class EventCommand {
+ private EventCommand() {
+ }
+
+ public static void trigger(CommandSender commandSender, String eventName) {
+ for (TimedEvent timedEvent : TimedEvent.getBlueprintEvents())
+ if (timedEvent.getCustomEventsConfigFields().getFilename().equals(eventName)) {
+ timedEvent.instantiateEvent();
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] Queued event " + eventName + " for the next valid time it can spawn. &cThis might take a while depending on the start conditions of the event."));
+ return;
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/TierSetSpawner.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/GetTierCommand.java
similarity index 63%
rename from src/main/java/com/magmaguy/elitemobs/commands/TierSetSpawner.java
rename to src/main/java/com/magmaguy/elitemobs/commands/admin/GetTierCommand.java
index f8fe78065..aefc73af9 100644
--- a/src/main/java/com/magmaguy/elitemobs/commands/TierSetSpawner.java
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/GetTierCommand.java
@@ -1,4 +1,4 @@
-package com.magmaguy.elitemobs.commands;
+package com.magmaguy.elitemobs.commands.admin;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
@@ -6,27 +6,29 @@
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
-public class TierSetSpawner {
+public class GetTierCommand {
+ private GetTierCommand() {
+ }
- public static void spawnTierItem(int tierLevel, Player player) {
+ public static void get(Player player, int tierLevel) {
- ItemStack helmet = new ItemStack(Material.DIAMOND_HELMET);
- ItemStack chestplate = new ItemStack(Material.DIAMOND_CHESTPLATE);
- ItemStack leggings = new ItemStack(Material.DIAMOND_LEGGINGS);
- ItemStack boots = new ItemStack(Material.DIAMOND_BOOTS);
- ItemStack sword = new ItemStack(Material.DIAMOND_SWORD);
- ItemStack axe = new ItemStack(Material.DIAMOND_AXE);
+ ItemStack helmet = new ItemStack(Material.NETHERITE_HELMET);
+ ItemStack chestplate = new ItemStack(Material.NETHERITE_CHESTPLATE);
+ ItemStack leggings = new ItemStack(Material.NETHERITE_LEGGINGS);
+ ItemStack boots = new ItemStack(Material.NETHERITE_BOOTS);
+ ItemStack sword = new ItemStack(Material.NETHERITE_SWORD);
+ ItemStack axe = new ItemStack(Material.NETHERITE_AXE);
ItemStack bow = new ItemStack(Material.BOW);
- if (tierLevel > 1) {
+ if (tierLevel > 8) {
- applyEnchantment(helmet, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel);
- applyEnchantment(chestplate, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel);
- applyEnchantment(leggings, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel);
- applyEnchantment(boots, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel);
- applyEnchantment(sword, Enchantment.DAMAGE_ALL, tierLevel);
- applyEnchantment(axe, Enchantment.DAMAGE_ALL, tierLevel);
- applyEnchantment(bow, Enchantment.ARROW_DAMAGE, tierLevel);
+ applyEnchantment(helmet, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel - 8);
+ applyEnchantment(chestplate, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel - 8);
+ applyEnchantment(leggings, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel - 8);
+ applyEnchantment(boots, Enchantment.PROTECTION_ENVIRONMENTAL, tierLevel - 8);
+ applyEnchantment(sword, Enchantment.DAMAGE_ALL, tierLevel - 8);
+ applyEnchantment(axe, Enchantment.DAMAGE_ALL, tierLevel - 8);
+ applyEnchantment(bow, Enchantment.ARROW_DAMAGE, tierLevel - 8);
}
@@ -38,8 +40,6 @@ public static void spawnTierItem(int tierLevel, Player player) {
player.getInventory().addItem(axe);
player.getInventory().addItem(bow);
- return;
-
}
private static void applyEnchantment(ItemStack itemStack, Enchantment enchantment, int tierLevel) {
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/KillHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/KillHandler.java
new file mode 100644
index 000000000..74372f822
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/KillHandler.java
@@ -0,0 +1,95 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties;
+import com.magmaguy.elitemobs.mobconstructor.mobdata.passivemobs.SuperMobProperties;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+
+public class KillHandler {
+
+ //TODO: FIX NPE ISSUE YOU FUCKING MORON
+
+ public static void killAggressiveMobs(CommandSender commandSender) {
+ int counter = 0;
+ for (EliteEntity eliteEntity : new ArrayList<>(EntityTracker.getEliteMobEntities().values())) {
+ eliteEntity.remove(RemovalReason.REMOVE_COMMAND);
+ counter++;
+ }
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Elite Mobs."));
+ }
+
+
+ public static void killPassiveMobs(CommandSender commandSender) {
+ int counter = 0;
+ for (LivingEntity superMobEntity : EntityTracker.getSuperMobs()) {
+ superMobEntity.remove();
+ counter++;
+ }
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Super Mobs."));
+ }
+
+ public static void killEntityType(CommandSender commandSender, EntityType entityType) {
+ if (EliteMobProperties.getValidMobTypes().contains(entityType)) {
+ int counter = 0;
+ for (EliteEntity eliteEntity : EntityTracker.getEliteMobEntities().values()) {
+ if (!eliteEntity.getLivingEntity().getType().equals(entityType)) continue;
+ eliteEntity.remove(RemovalReason.REMOVE_COMMAND);
+ counter++;
+ }
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Elite " + entityType.toString() + "."));
+ } else if (SuperMobProperties.superMobTypeList.contains(entityType)) {
+ int counter = 0;
+ for (LivingEntity superMobEntity : EntityTracker.getSuperMobs()) {
+ if (!superMobEntity.getType().equals(entityType)) continue;
+ superMobEntity.remove();
+ counter++;
+ }
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Super " + entityType.toString() + "."));
+ } else
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &cNot a valid entity type for EliteMobs!"));
+ }
+
+ public static void radiusKillAggressiveMobs(Player player, int radius) {
+ int counter = 0;
+ for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(entity);
+ if (eliteEntity != null)
+ eliteEntity.remove(RemovalReason.REMOVE_COMMAND);
+ }
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Elite Mobs."));
+ }
+
+ public static void radiusKillPassiveMobs(Player player, int radius) {
+ int counter = 0;
+ for (Entity entity : player.getNearbyEntities(radius, radius, radius))
+ if (EntityTracker.isSuperMob(entity)) {
+ entity.remove();
+ counter++;
+ }
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Super Mobs."));
+ }
+
+ public static void radiusKillSpecificMobs(Player player, EntityType entityType, int radius) {
+ int counter = 0;
+ for (Entity entity : player.getNearbyEntities(radius, radius, radius)) {
+ if (entity.getType().equals(entityType) && (EntityTracker.isEliteMob(entity))) {
+ ((EliteEntity) entity).remove(RemovalReason.KILL_COMMAND);
+ counter++;
+ } else if (entity.getType().equals(entityType) && EntityTracker.isSuperMob(entity)) {
+ EntityTracker.unregister(entity, RemovalReason.KILL_COMMAND);
+ counter++;
+ }
+ }
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Killed " + counter + " Elite Mobs."));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/LootCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/LootCommand.java
new file mode 100644
index 000000000..45f7f6872
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/LootCommand.java
@@ -0,0 +1,36 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.items.customitems.CustomItem;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+/**
+ * Created by MagmaGuy on 01/05/2017.
+ */
+public class LootCommand {
+
+ public static void get(Player player, String args1) {
+ CustomItem customItem = CustomItem.getCustomItem(args1);
+ if (customItem == null) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &cFile name " + args1 + " &cis not a valid custom item file name!"));
+ return;
+ }
+ player.getInventory().addItem(customItem.generateDefaultsItemStack(player, false, null));
+ }
+
+ public static void give(CommandSender commandSender, String playerString, String args1) {
+ CustomItem customItem = CustomItem.getCustomItem(args1);
+ if (customItem == null) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &cFile name " + args1 + " &cis not a valid custom item file name!"));
+ return;
+ }
+ Player player = Bukkit.getPlayer(playerString);
+ if (player == null)
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &cTried to give item to invalid player!"));
+ else
+ player.getInventory().addItem(customItem.generateDefaultsItemStack(player, false, null));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/NPCCommands.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/NPCCommands.java
new file mode 100644
index 000000000..ee1065718
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/NPCCommands.java
@@ -0,0 +1,44 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.config.npcs.NPCsConfig;
+import com.magmaguy.elitemobs.config.npcs.NPCsConfigFields;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.npcs.NPCEntity;
+import com.magmaguy.elitemobs.utils.Round;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+public class NPCCommands {
+
+ public static void set(Player player, String npcFileName) {
+
+ NPCsConfigFields npCsConfigFields = NPCsConfig.getNpcEntities().get(npcFileName);
+ if (npCsConfigFields == null) {
+ player.sendMessage("[EliteMobs] Invalid NPC filename.");
+ return;
+ }
+
+ Location playerLocation = player.getLocation();
+
+ String location = playerLocation.getWorld().getName() + ","
+ + Round.twoDecimalPlaces(playerLocation.getX()) + ","
+ + Round.twoDecimalPlaces(playerLocation.getY()) + ","
+ + Round.twoDecimalPlaces(playerLocation.getZ()) + ","
+ + Round.twoDecimalPlaces(playerLocation.getYaw()) + ","
+ + Round.twoDecimalPlaces(playerLocation.getPitch());
+
+ try {
+ for (NPCEntity npcEntity : EntityTracker.getNpcEntities().values())
+ if (npcEntity.npCsConfigFields.equals(npCsConfigFields))
+ npcEntity.remove(RemovalReason.REMOVE_COMMAND);
+ } catch (Exception ex) {
+ }
+
+ npCsConfigFields.setEnabled(true);
+ npCsConfigFields.setLocation(location);
+ new NPCEntity(npCsConfigFields);
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/RelativeCoordinatesCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/RelativeCoordinatesCommand.java
new file mode 100644
index 000000000..f7b52ca3c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/RelativeCoordinatesCommand.java
@@ -0,0 +1,44 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.powerstances.GenericRotationMatrixMath;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class RelativeCoordinatesCommand {
+ public static void get(Player player, String minidungeonString) {
+
+ Minidungeon minidungeon = Minidungeon.getMinidungeons().get(minidungeonString);
+ if (minidungeon == null) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Minidungeons name " + minidungeonString + " &4isn't valid!"));
+ return;
+ }
+
+ if (!minidungeon.isInstalled()) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Minidungeon isn't installed! Can't get the relative location for uninstalled Minidungeons!"));
+ return;
+ }
+
+ Location anchorpoint = minidungeon.getDungeonPackagerConfigFields().getAnchorPoint();
+
+ if (anchorpoint == null) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Something went wrong and made the anchor point not valid!"));
+ return;
+ }
+
+ Vector relativeVector = player.getLocation().clone().subtract(anchorpoint).toVector();
+ if (minidungeon.getDungeonPackagerConfigFields().getRotation() != 0)
+ GenericRotationMatrixMath.rotateVectorYAxis(minidungeon.getDungeonPackagerConfigFields().getRotation(), anchorpoint, relativeVector);
+
+ String relativePosition = relativeVector.getBlockX() + ", "
+ + relativeVector.getBlockY() + ", "
+ + relativeVector.getBlockZ();
+
+ player.sendMessage(ChatColorConverter.convert(
+ "[EliteMobs] Relative position to anchor point of " + minidungeon.getDungeonPackagerConfigFields().getName() + ": " + relativePosition));
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/ReloadCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/ReloadCommand.java
new file mode 100644
index 000000000..d29dc169a
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/ReloadCommand.java
@@ -0,0 +1,13 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import org.bukkit.command.CommandSender;
+
+public class ReloadCommand {
+ public static void reload(CommandSender commandSender) {
+ MetadataHandler.PLUGIN.onDisable();
+ MetadataHandler.PLUGIN.onLoad();
+ MetadataHandler.PLUGIN.onEnable();
+ commandSender.sendMessage("[EliteMobs] Reload attempted. This may not 100% work. Restart instead if it didn't!!");
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java
new file mode 100644
index 000000000..50c0a1eb7
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java
@@ -0,0 +1,67 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.api.internal.RemovalReason;
+import com.magmaguy.elitemobs.config.dungeonpackager.DungeonPackagerConfigFields;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.EliteEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.RegionalBossEntity;
+import com.magmaguy.elitemobs.npcs.NPCEntity;
+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.EntityDamageByEntityEvent;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+public class RemoveCommand {
+ private static final Set removingPlayers = new HashSet<>();
+
+ private RemoveCommand() {
+ }
+
+ public static void remove(Player player) {
+ if (removingPlayers.contains(player.getUniqueId())) {
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &aYou are no longer removing elites!"));
+ removingPlayers.remove(player.getUniqueId());
+ } else {
+ removingPlayers.add(player.getUniqueId());
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &cYou are now removing elites when you punch them! Run &a/em remove &cagain to stop removing elites!"));
+ }
+ }
+
+ public static class RemoveCommandEvents implements Listener {
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void removeEliteEntity(EntityDamageByEntityEvent event) {
+ if (!removingPlayers.contains(event.getDamager().getUniqueId())) return;
+ EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity());
+ if (eliteEntity == null) return;
+ if (eliteEntity instanceof RegionalBossEntity)
+ event.getDamager().sendMessage(ChatColorConverter.convert(
+ "&8[EliteMobs] &cRemoved a spawn location for boss " +
+ ((RegionalBossEntity) eliteEntity).getCustomBossesConfigFields().getFilename()));
+ if (eliteEntity instanceof RegionalBossEntity &&
+ ((CustomBossEntity) eliteEntity).getMinidungeon() != null &&
+ ((CustomBossEntity) eliteEntity).getMinidungeon().getDungeonPackagerConfigFields().getDungeonLocationType()
+ .equals(DungeonPackagerConfigFields.DungeonLocationType.SCHEMATIC))
+ ((CustomBossEntity) eliteEntity).getMinidungeon().removeRelativeLocation((RegionalBossEntity) eliteEntity);
+ eliteEntity.remove(RemovalReason.REMOVE_COMMAND);
+ event.setCancelled(true);
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void removeNPC(EntityDamageByEntityEvent event) {
+ if (!removingPlayers.contains(event.getDamager().getUniqueId())) return;
+ NPCEntity npcEntity = EntityTracker.getNPCEntity(event.getEntity());
+ if (npcEntity == null) return;
+ npcEntity.remove(RemovalReason.REMOVE_COMMAND);
+ event.setCancelled(true);
+ }
+ }
+
+}
+
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/SimLootCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/SimLootCommand.java
new file mode 100644
index 000000000..8b0d37391
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/SimLootCommand.java
@@ -0,0 +1,56 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.config.ItemSettingsConfig;
+import com.magmaguy.elitemobs.items.EliteItemLore;
+import com.magmaguy.elitemobs.items.LootTables;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+/**
+ * Created by MagmaGuy on 08/06/2017.
+ */
+public class SimLootCommand {
+ public static void runMultipleTimes(Player player, int level, int timesToRun) {
+ for (int i = 0; i < timesToRun; i++)
+ run(player, level);
+ }
+
+ public static void runMultipleTimes(CommandSender player, int level, int timesToRun, String playerName) {
+ Player targetPlayer = Bukkit.getPlayer(playerName);
+ if (targetPlayer == null) {
+ player.sendMessage(ChatColor.RED + "[EliteMobs] Could not send item to player " + playerName + " - player with this name was not found!");
+ return;
+ }
+ for (int i = 0; i < timesToRun; i++)
+ run(targetPlayer, level);
+ player.sendMessage("[EliteMobs] Finished running simulation command for player " + playerName + " " + timesToRun + " times at level " + level + " .");
+ }
+
+ public static void run(Player player, int level) {
+ try {
+ ItemStack itemStack = LootTables.generateLoot(level, player.getLocation(), player);
+ if (itemStack == null)
+ player.sendMessage(ChatColorConverter.convert(ItemSettingsConfig.getSimlootMessageFailure()));
+ else {
+ EliteItemLore eliteItemLore = new EliteItemLore(itemStack, false);
+ player.sendMessage(ChatColorConverter.convert(ItemSettingsConfig.getSimlootMessageSuccess().replace("$itemName", eliteItemLore.getItemStack().getItemMeta().getDisplayName())));
+ }
+ } catch (Exception ex) {
+ player.sendMessage(ChatColorConverter.convert(ItemSettingsConfig.getSimlootMessageFailure()));
+ }
+ }
+
+ public static void run(CommandSender player, int level, String playerName) {
+ Player targetPlayer = Bukkit.getPlayer(playerName);
+ if (targetPlayer == null) {
+ player.sendMessage(ChatColor.RED + "[EliteMobs] Could not send item to player " + playerName + " - player with this name was not found!");
+ return;
+ }
+ run(targetPlayer, level);
+ player.sendMessage("[EliteMobs] Finished running simulation command for player " + playerName + " at level " + level + " .");
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/StatsCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/StatsCommand.java
new file mode 100644
index 000000000..a8f0725b9
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/StatsCommand.java
@@ -0,0 +1,108 @@
+package com.magmaguy.elitemobs.commands.admin;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.EliteMobs;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.entitytracker.EntityTracker;
+import com.magmaguy.elitemobs.mobconstructor.custombosses.RegionalBossEntity;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import com.magmaguy.elitemobs.utils.Round;
+import org.bukkit.Bukkit;
+import org.bukkit.World;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+
+/**
+ * Created by MagmaGuy on 01/05/2017.
+ */
+public class StatsCommand {
+
+ public static void statsHandler(CommandSender commandSender) {
+
+ int aggressiveCount = 0;
+ int passiveCount = 0;
+
+ HashMap entitiesCounted = new HashMap<>();
+
+ for (World world : EliteMobs.validWorldList)
+ for (LivingEntity livingEntity : world.getLivingEntities())
+ if (EntityTracker.isEliteMob(livingEntity)) {
+ aggressiveCount++;
+ if (!entitiesCounted.containsKey(livingEntity.getType()))
+ entitiesCounted.put(livingEntity.getType(), 1);
+ else
+ entitiesCounted.put(livingEntity.getType(), entitiesCounted.get(livingEntity.getType()) + 1);
+ } else if (EntityTracker.isSuperMob(livingEntity)) {
+ passiveCount++;
+ if (!entitiesCounted.containsKey(livingEntity.getType()))
+ entitiesCounted.put(livingEntity.getType(), 1);
+ else
+ entitiesCounted.put(livingEntity.getType(), entitiesCounted.get(livingEntity.getType()) + 1);
+ }
+
+ StringBuilder breakdownString = new StringBuilder("&2Breakdown: &a");
+
+ for (EntityType entityType : entitiesCounted.keySet()) {
+ breakdownString.append(entitiesCounted.get(entityType)).append(" ").append(entityType).append("&2, &a");
+ }
+
+ double highestThreat = 0;
+ String highestThreatUser = "";
+ double threatAverage = 0;
+ int highestGuildRank = 0;
+ String highestGuildUser = "";
+ double guildRankAverage = 0;
+ Player highestGuildRankPlayer = null;
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ double currentTier = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getFullPlayerTier(true);
+ threatAverage += currentTier;
+ int currentGuildRank = GuildRank.getActiveGuildRank(player);
+ guildRankAverage += currentGuildRank;
+ if (currentTier > highestThreat) {
+ highestThreat = currentTier;
+ highestThreatUser = player.getDisplayName();
+ }
+ if (currentGuildRank > highestGuildRank) {
+ highestGuildRankPlayer = player;
+ highestGuildRank = currentGuildRank;
+ highestGuildUser = player.getDisplayName();
+ }
+ }
+ threatAverage /= Bukkit.getOnlinePlayers().size();
+ guildRankAverage /= Bukkit.getOnlinePlayers().size();
+
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "§5§m-----------------------------------------------------"));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] §a§lEliteMobs v. " + Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS).getDescription().getVersion() + " stats:"));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] &2There are currently §l§6" + (aggressiveCount + passiveCount) + " §f§2EliteMobs mobs entities in the world, of which &a"
+ + aggressiveCount + " &2are Elite Mobs and &a" + passiveCount + " &2are Super Mobs."));
+ commandSender.sendMessage(ChatColorConverter.convert(breakdownString.toString()));
+ if (highestGuildRankPlayer == null) return;
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] &2Highest online threat tier: &a" + highestThreatUser + " &2at total threat tier &a" + highestThreat));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] &2Average threat tier: &a" + Round.twoDecimalPlaces(threatAverage)));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] &2Highest adventurer's guild tier: &a" + highestGuildUser + " &2at guild rank &a" + GuildRank.getRankName(GuildRank.getGuildPrestigeRank(highestGuildRankPlayer), highestGuildRank) + " &2(&a" + highestGuildRank + "&2)"));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "&7[EM] &2Average guild rank: &a" + Round.twoDecimalPlaces(guildRankAverage)));
+ commandSender.sendMessage(ChatColorConverter.convert(
+ "§5§m-----------------------------------------------------"));
+ commandSender.sendMessage("Tracked boss count: " + EntityTracker.getEliteMobEntities().size());
+ commandSender.sendMessage("Tracked NPC count: " + EntityTracker.getNpcEntities().size());
+ commandSender.sendMessage("Tracked visual item count: " + EntityTracker.getItemVisualEffects().size());
+ int loadedCounter = 0;
+ for (RegionalBossEntity regionalBossEntity : RegionalBossEntity.getRegionalBossEntities())
+ if (regionalBossEntity.isValid())
+ loadedCounter++;
+ commandSender.sendMessage(ChatColorConverter.convert("&7[EM] &2There are &c" + RegionalBossEntity.getRegionalBossEntities().size() + " &2Regional Bosses installed, of which &c" + loadedCounter + " &2are currently loaded."));
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/VersionHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/VersionCommand.java
similarity index 68%
rename from src/main/java/com/magmaguy/elitemobs/commands/VersionHandler.java
rename to src/main/java/com/magmaguy/elitemobs/commands/admin/VersionCommand.java
index a3962ffb4..b32342c74 100644
--- a/src/main/java/com/magmaguy/elitemobs/commands/VersionHandler.java
+++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/VersionCommand.java
@@ -1,17 +1,18 @@
-package com.magmaguy.elitemobs.commands;
+package com.magmaguy.elitemobs.commands.admin;
import com.magmaguy.elitemobs.MetadataHandler;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
-public class VersionHandler {
+public class VersionCommand {
- public static void versionCommand(CommandSender commandSender, String[] args){
+ private VersionCommand() {
+ }
+ public static void getVersion(CommandSender commandSender) {
commandSender.sendMessage(ChatColor.DARK_GREEN + "[EliteMobs]" + ChatColor.WHITE + " version " + ChatColor.GREEN +
Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS).getDescription().getVersion());
-
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/combat/CheckTierCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/combat/CheckTierCommand.java
new file mode 100644
index 000000000..1dfce03ab
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/combat/CheckTierCommand.java
@@ -0,0 +1,27 @@
+package com.magmaguy.elitemobs.commands.combat;
+
+import com.magmaguy.elitemobs.adventurersguild.GuildRank;
+import com.magmaguy.elitemobs.config.commands.premade.CheckTierConfig;
+import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory;
+import org.bukkit.entity.Player;
+
+public class CheckTierCommand {
+
+ public CheckTierCommand(Player player) {
+
+ double gearTier = ElitePlayerInventory.playerInventories.get(player.getUniqueId()).getFullPlayerTier(true);
+ double guildRank = GuildRank.getActiveGuildRank(player);
+ if (guildRank == 0)
+ guildRank = -10;
+ else
+ guildRank--;
+ guildRank = (guildRank * 0.2);
+
+ player.sendMessage(CheckTierConfig.message1.replace("$tier", gearTier + ""));
+ player.sendMessage(CheckTierConfig.message2.replace("$tier", guildRank + ""));
+ player.sendMessage(CheckTierConfig.message3.replace("$tier", (gearTier + guildRank) + ""));
+
+ }
+
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/guiconfig/SignatureItem.java b/src/main/java/com/magmaguy/elitemobs/commands/guiconfig/SignatureItem.java
deleted file mode 100644
index 2707d80ca..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/guiconfig/SignatureItem.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands.guiconfig;
-
-import org.bukkit.Material;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.meta.SkullMeta;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Created by MagmaGuy on 12/11/2017.
- */
-public class SignatureItem {
-
- public static final ItemStack SIGNATURE_ITEMSTACK = setSignatureItem();
-
- private static ItemStack setSignatureItem() {
-
- ItemStack signature = new ItemStack(Material.SKULL_ITEM, 1, (short) 3);
- SkullMeta signatureSkullMeta = (SkullMeta) signature.getItemMeta();
- signatureSkullMeta.setOwner("magmaguy");
- signatureSkullMeta.setDisplayName("EliteMobs by MagmaGuy");
- List signatureList = new ArrayList<>();
- signatureList.add("Support the plugins you enjoy!");
- signatureSkullMeta.setLore(signatureList);
- signature.setItemMeta(signatureSkullMeta);
-
- return signature;
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/guild/AdventurersGuildCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/guild/AdventurersGuildCommand.java
new file mode 100644
index 000000000..412016c15
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/guild/AdventurersGuildCommand.java
@@ -0,0 +1,80 @@
+package com.magmaguy.elitemobs.commands.guild;
+
+import com.magmaguy.elitemobs.adventurersguild.GuildRankMenuHandler;
+import com.magmaguy.elitemobs.api.PlayerPreTeleportEvent;
+import com.magmaguy.elitemobs.api.PlayerTeleportEvent;
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import com.magmaguy.elitemobs.config.CombatTagConfig;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+
+public class AdventurersGuildCommand {
+
+ public static void adventurersGuildCommand(Player player) {
+ if (adventurersGuildTeleport(player)) return;
+ if (player.hasPermission("elitemobs.adventurersguild.command"))
+ GuildRankMenuHandler.initializeGuildRankMenu(player);
+ else
+ player.sendMessage("Missing permission: elitemobs.adventurersguild.command / elitemobs.adventurersguild.teleport");
+ }
+
+ public static boolean adventurersGuildTeleport(Player player) {
+ if (!player.hasPermission("elitemobs.adventurersguild.teleport")) return false;
+ if (!AdventurersGuildConfig.isAgTeleport()) return false;
+ if (AdventurersGuildConfig.getGuildWorldLocation() == null)
+ defineTeleportLocation();
+ if (AdventurersGuildConfig.getGuildWorldLocation() == null) return false;
+
+ if (CombatTagConfig.isEnableCombatTag())
+ new EventCaller(new PlayerPreTeleportEvent(player, AdventurersGuildConfig.getGuildWorldLocation()));
+ else
+ new EventCaller(new PlayerTeleportEvent(player, AdventurersGuildConfig.getGuildWorldLocation()));
+
+ return true;
+
+ }
+
+ public static Location defineTeleportLocation() {
+
+ for (World world : Bukkit.getWorlds())
+ if (world.getName().equals(AdventurersGuildConfig.getGuildWorldName())) {
+ double x = 0, y = 0, z = 0;
+ float yaw = 0, pitch = 0;
+ int counter = 0;
+
+ for (String substring : AdventurersGuildConfig.getGuildLocationString().split(",")) {
+ switch (counter) {
+ case 0:
+ x = Double.parseDouble(substring);
+ break;
+ case 1:
+ y = Double.parseDouble(substring);
+ break;
+ case 2:
+ z = Double.parseDouble(substring);
+ break;
+ case 3:
+ yaw = Float.parseFloat(substring);
+ break;
+ case 4:
+ pitch = Float.parseFloat(substring);
+ break;
+ }
+ counter++;
+
+ }
+
+ Location location = new Location(world, x, y, z, yaw, pitch);
+ AdventurersGuildConfig.setGuildWorldLocation(location);
+ return location;
+
+ }
+
+ return null;
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/quests/QuestCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/quests/QuestCommand.java
new file mode 100644
index 000000000..1c7432204
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/quests/QuestCommand.java
@@ -0,0 +1,60 @@
+package com.magmaguy.elitemobs.commands.quests;
+
+import com.magmaguy.elitemobs.playerdata.database.PlayerData;
+import com.magmaguy.elitemobs.quests.CustomQuest;
+import com.magmaguy.elitemobs.quests.Quest;
+import com.magmaguy.elitemobs.quests.QuestTracking;
+import com.magmaguy.elitemobs.quests.playercooldowns.PlayerQuestCooldowns;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+public class QuestCommand {
+
+ private QuestCommand() {
+ }
+
+ public static void completeQuest(String questID, Player player) {
+ try {
+ Quest.completeQuest(UUID.fromString(questID), player);
+ } catch (Exception ex) {
+ player.sendMessage(ChatColor.RED + "[EliteMobs] Invalid quest ID!");
+ }
+ }
+
+ // /em quest join questFilename
+ public static void joinQuest(String questID, Player player) {
+ CustomQuest.startQuest(questID, player);
+ }
+
+ public static void trackQuest(String questID, Player player) {
+ QuestTracking.toggleTracking(player, questID);
+ }
+
+ // /em quest leave questFilename
+ public static void leaveQuest(Player player, String questID) {
+ Quest.stopPlayerQuest(player, questID);
+ }
+
+ public static void resetQuests(CommandSender commandSender, String playerString) {
+ Player player = Bukkit.getPlayer(playerString);
+ if (player == null) {
+ commandSender.sendMessage("[EliteMobs] Error - player name not valid!");
+ return;
+ }
+ PlayerQuestCooldowns.resetPlayerQuestCooldowns(player);
+ commandSender.sendMessage("[EliteMobs] Successfully reset quests for player " + playerString);
+ }
+
+ public static void completeQuest(Player player){
+ for (Quest quest : new ArrayList(PlayerData.getQuests(player.getUniqueId()))){
+ quest.getQuestObjectives().setForceOver(true);
+ Quest.completeQuest(quest.getQuestID(), player);
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/setup/SetupMenu.java b/src/main/java/com/magmaguy/elitemobs/commands/setup/SetupMenu.java
new file mode 100644
index 000000000..9267b2c3c
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/commands/setup/SetupMenu.java
@@ -0,0 +1,275 @@
+package com.magmaguy.elitemobs.commands.setup;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.api.PlayerTeleportEvent;
+import com.magmaguy.elitemobs.commands.guild.AdventurersGuildCommand;
+import com.magmaguy.elitemobs.config.AdventurersGuildConfig;
+import com.magmaguy.elitemobs.dungeons.Minidungeon;
+import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility;
+import com.magmaguy.elitemobs.utils.DiscordLinks;
+import com.magmaguy.elitemobs.utils.EventCaller;
+import com.magmaguy.elitemobs.utils.ItemStackGenerator;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import com.magmaguy.elitemobs.worlds.CustomWorldLoading;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.inventory.Inventory;
+
+import java.util.*;
+
+public class SetupMenu {
+
+ public static Map setupMenus = new HashMap<>();
+
+ Inventory inventory;
+ Player player;
+ ArrayList validSlots = new ArrayList<>(Arrays.asList(10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23,
+ 24, 25, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43));
+ HashMap minidungeonHashMap = new HashMap<>();
+ boolean adventurersGuildIsDownloaded = false;
+
+ public SetupMenu(Player player) {
+ this.inventory = Bukkit.createInventory(player, 54, "Setup menu");
+ this.player = player;
+ //reserve adventurer's guild
+ adventurersGuildWorldStatus();
+ //iterate through dungeons
+ dungeonStatuses();
+ setupMenus.put(inventory, this);
+ player.openInventory(inventory);
+ }
+
+ private void adventurersGuildWorldStatus() {
+ String state = "Adventurer's Guild world is";
+ String lore;
+ Material material;
+ if (CustomWorldLoading.adventurersGuildWorldExists())
+ adventurersGuildIsDownloaded = true;
+
+ if (!adventurersGuildIsDownloaded) {
+ material = Material.RED_STAINED_GLASS_PANE;
+ lore = ChatColor.RED + "Not downloaded! Click to download!";
+ } else {
+ if (!AdventurersGuildConfig.isGuildWorldIsEnabled()) {
+ material = Material.ORANGE_STAINED_GLASS_PANE;
+ lore = ChatColor.RED + "Not setup! Click to install!";
+ } else {
+ material = Material.GREEN_STAINED_GLASS_PANE;
+ lore = ChatColor.GREEN + "Working correctly! Click to uninstall!";
+ }
+ }
+ inventory.setItem(validSlots.get(0), ItemStackGenerator.generateItemStack(material, state, new ArrayList<>(Arrays.asList(lore))));
+ }
+
+ private void dungeonStatuses() {
+ //continue counting from used inventory slots
+ int counter = 1;
+ for (Minidungeon minidungeon : Minidungeon.getMinidungeons().values()) {
+
+ if (!Bukkit.getPluginManager().isPluginEnabled("WorldGuard"))
+ inventory.setItem(validSlots.get(counter), ItemStackGenerator.generateItemStack(Material.RED_STAINED_GLASS_PANE,
+ ChatColorConverter.convert("&4You need WorldGuard to install Minidungeons correctly!")));
+ else
+
+ switch (minidungeon.getDungeonPackagerConfigFields().getDungeonLocationType()) {
+ case WORLD:
+ addWorldDungeon(minidungeon, counter);
+ break;
+ case SCHEMATIC:
+ addSchematicDungeon(minidungeon, counter);
+ break;
+ default:
+ new WarningMessage("Dungeon " + minidungeon.getDungeonPackagerConfigFields().getFilename() + " does not have a valid location type and therefore can't be set up automatically!");
+ break;
+ }
+ minidungeonHashMap.put(validSlots.get(counter), minidungeon);
+ counter++;
+
+ }
+ }
+
+ private void addWorldDungeon(Minidungeon minidungeon, int counter) {
+
+ String itemName = minidungeon.getDungeonPackagerConfigFields().getName();
+ List lore = new ArrayList<>();
+
+ addSize(lore, minidungeon);
+ //boss count can't be calculated ahead of time here, unfortunately
+ addInstallationString(lore, minidungeon);
+
+ lore = ChatColorConverter.convert(lore);
+ inventory.setItem(validSlots.get(counter), ItemStackGenerator.generateItemStack(getMaterial(minidungeon), itemName, lore));
+ }
+
+ private void addSchematicDungeon(Minidungeon minidungeon, int counter) {
+ if (!Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
+ inventory.setItem(validSlots.get(counter), ItemStackGenerator.generateItemStack(Material.RED_STAINED_GLASS_PANE, ChatColorConverter.convert("&4You need WorldEdit to use this!")));
+ return;
+ }
+
+ String itemName = minidungeon.getDungeonPackagerConfigFields().getName();
+
+ List lore = new ArrayList<>();
+ if (minidungeon.getDungeonPackagerConfigFields().getCustomInfo() != null)
+ lore.addAll(minidungeon.getDungeonPackagerConfigFields().getCustomInfo());
+ addSize(lore, minidungeon);
+ addBossCount(lore, minidungeon);
+ addInstallationString(lore, minidungeon);
+
+ lore = ChatColorConverter.convert(lore);
+
+ inventory.setItem(validSlots.get(counter), ItemStackGenerator.generateItemStack(getMaterial(minidungeon), itemName, lore));
+ }
+
+ private Material getMaterial(Minidungeon minidungeon) {
+ if (minidungeon.isInstalled())
+ return Material.GREEN_STAINED_GLASS_PANE;
+ if (minidungeon.isDownloaded() && minidungeon.isBossesDownloaded())
+ return Material.YELLOW_STAINED_GLASS_PANE;
+ if (minidungeon.isDownloaded() && !minidungeon.isBossesDownloaded())
+ return Material.ORANGE_STAINED_GLASS_PANE;
+ return Material.RED_STAINED_GLASS_PANE;
+ }
+
+ private void addSize(List lore, Minidungeon minidungeon) {
+ lore.add("&fSize: " + minidungeon.getDungeonPackagerConfigFields().getDungeonSizeCategory().toString());
+ }
+
+ private void addBossCount(List lore, Minidungeon minidungeon) {
+ try {
+ lore.add("&fRegional boss count: " + minidungeon.getRelativeBossLocations().getBossCount());
+ } catch (Exception ex) {
+ //todo: fix this
+ //new WarningMessage("Failed to determine regional boss count! Are the relative dungeon locations correct?");
+ }
+ }
+
+ private void addInstallationString(List lore, Minidungeon minidungeon) {
+ String status = "&fStatus: ";
+ if (minidungeon.isInstalled()) {
+ lore.add(status + "&2already installed!");
+ lore.add("&cClick to uninstall!");
+ return;
+ }
+ if (!minidungeon.isDownloaded()) {
+ lore.add(status + "&4not downloaded!");
+ lore.add("&4Download this at");
+ lore.add("&9" + minidungeon.getDungeonPackagerConfigFields().getDownloadLink() + " &f!");
+ return;
+ }
+ if (!minidungeon.isBossesDownloaded()) {
+ lore.add("&4Minidungeon boss files are not downloaded!");
+ lore.add("&4Download this at");
+ lore.add("&9" + minidungeon.getDungeonPackagerConfigFields().getDownloadLink() + " &f!");
+ return;
+ }
+ lore.add(status + "&aready to install!");
+ lore.add("&2Click to install!");
+ }
+
+
+ public static class SetupMenuListeners implements Listener {
+ @EventHandler(ignoreCancelled = true)
+ public void onInventoryInteraction(InventoryClickEvent event) {
+ SetupMenu setupMenu = setupMenus.get(event.getInventory());
+ if (setupMenu == null) return;
+ event.setCancelled(true);
+ Player player = (Player) event.getWhoClicked();
+ //for permissions mode
+ //for adventurer's guild world
+ if (event.getSlot() == 10) {
+ //case where Adventurer's Guild Hub isn't downloaded
+ if (!setupMenu.adventurersGuildIsDownloaded) {
+ player.closeInventory();
+ player.sendMessage("----------------------------------------------------");
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2Adventurer's Guild Hub download link: https://magmaguy.itch.io/"));
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &aOnce downloaded, follow this setup guide: &9&nhttps://youtu.be/boRg2X4qhw4"));
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2Need help? " + DiscordLinks.mainLink));
+ player.sendMessage("----------------------------------------------------");
+ } else {
+ //case for install
+ if (!AdventurersGuildConfig.isGuildWorldIsEnabled()) {
+ try {
+ player.closeInventory();
+ player.sendMessage("----------------------------------------------------");
+ CustomWorldLoading.startupWorldInitialization();
+ AdventurersGuildCommand.defineTeleportLocation();
+ AdventurersGuildConfig.toggleGuildInstall();
+ if (Bukkit.getPluginManager().isPluginEnabled("WorldGuard")) {
+ WorldGuardCompatibility.protectWorldMinidugeonArea(AdventurersGuildCommand.defineTeleportLocation());
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2The Adventurer's Guild Hub has been protected against griefing and mob spawning (among others)!"));
+ } else
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4It is highly recommended you install WorldGuard to protect the Adventurer's Guild Hub World! Reinstall the hub through /em setup after installing WorldGuard in order to automatically protect the area!"));
+ PlayerTeleportEvent playerTeleportEvent = new PlayerTeleportEvent(player, AdventurersGuildConfig.getGuildWorldLocation());
+ new EventCaller(playerTeleportEvent);
+ if (!playerTeleportEvent.isCancelled())
+ player.teleport(AdventurersGuildConfig.getGuildWorldLocation());
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2Successfully installed Adventurer's Guild Hub! Do &a/ag &2to go there and talk to the transporter or open the Teleports page in /em to go back!"));
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2Need help? &9&n" + DiscordLinks.mainLink));
+ player.sendMessage("----------------------------------------------------");
+ } catch (Exception e) {
+ player.closeInventory();
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed to install Adventurer's Guild Hub! Report this to the dev!"));
+ player.sendMessage("----------------------------------------------------");
+ e.printStackTrace();
+ }
+ //case for uninstall
+ } else {
+ try {
+ player.closeInventory();
+ Bukkit.unloadWorld(AdventurersGuildConfig.getGuildWorldLocation().getWorld(), true);
+ AdventurersGuildConfig.setGuildWorldLocation(null);
+ AdventurersGuildConfig.toggleGuildInstall();
+ player.sendMessage("----------------------------------------------------");
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &2Successfully uninstalled Adventurer's Guild Hub!"));
+ player.sendMessage("----------------------------------------------------");
+ } catch (Exception e) {
+ player.closeInventory();
+ player.sendMessage("----------------------------------------------------");
+ player.sendMessage(ChatColorConverter.convert("&8[EliteMobs] &4Failed to uninstall Adventurer's Guild Hub! Report this to the dev!"));
+ player.sendMessage("----------------------------------------------------");
+ e.printStackTrace();
+ }
+ }
+ }
+ return;
+ }
+ //for minidungeons
+ Minidungeon minidungeon = setupMenu.minidungeonHashMap.get(event.getSlot());
+ if (minidungeon != null) {
+ if (!minidungeon.isDownloaded()) {
+ player.sendMessage("----------------------------------------------------");
+ player.sendMessage(ChatColorConverter.convert("&4Download this at &9" + minidungeon.getDungeonPackagerConfigFields().getDownloadLink() + " &4!"));
+ player.sendMessage("----------------------------------------------------");
+ player.closeInventory();
+ setupMenus.remove(event.getInventory());
+ return;
+ }
+ if (!minidungeon.isBossesDownloaded()) {
+ player.sendMessage("----------------------------------------------------");
+ player.sendMessage(ChatColorConverter.convert("&4You are missing the boss files for this minidungeon!"));
+ player.sendMessage(ChatColorConverter.convert("&4Download this at &9" + minidungeon.getDungeonPackagerConfigFields().getDownloadLink() + " &4!"));
+ player.sendMessage("----------------------------------------------------");
+ player.closeInventory();
+ setupMenus.remove(event.getInventory());
+ return;
+ }
+ minidungeon.buttonToggleBehavior(player);
+ setupMenus.remove(event.getInventory());
+ player.closeInventory();
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true)
+ public void onInventoryClose(InventoryCloseEvent event) {
+ setupMenus.remove(event.getInventory());
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/shops/CustomShopHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/shops/CustomShopHandler.java
deleted file mode 100644
index 2a34f505f..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/shops/CustomShopHandler.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands.shops;
-
-import com.magmaguy.elitemobs.commands.guiconfig.SignatureItem;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.EconomySettingsConfig;
-import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.economy.UUIDFilter;
-import com.magmaguy.elitemobs.items.CustomItemConstructor;
-import com.magmaguy.elitemobs.items.ItemWorthCalculator;
-import com.magmaguy.elitemobs.items.ObfuscatedSignatureLoreData;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.List;
-import java.util.Random;
-
-/**
- * Created by MagmaGuy on 20/06/2017.
- */
-public class CustomShopHandler implements Listener {
-
- public static final String SHOP_NAME = ConfigValues.economyConfig.getString(EconomySettingsConfig.CUSTOM_SHOP_NAME);
-
- public void initializeShop(Player player) {
-
- Inventory shopInventory = Bukkit.createInventory(player, 54, SHOP_NAME);
-
- populateShop(shopInventory);
-
- player.openInventory(shopInventory);
-
- }
-
- private void populateShop(Inventory shopInventory) {
-
- SharedShopElements.shopHeader(shopInventory);
- shopContents(shopInventory);
-
- }
-
- private static List validSlots = (List) ConfigValues.economyConfig.getList(EconomySettingsConfig.CUSTOM_SHOP_VALID_SLOTS);
-
- private void shopContents(Inventory shopInventory) {
-
- //Anything after 8 is populated
- Random random = new Random();
-
- for (int i : validSlots) {
-
- int itemEntryIndex = random.nextInt(CustomItemConstructor.customItemList.size());
-
- shopInventory.setItem(i, CustomItemConstructor.customItemList.get(itemEntryIndex));
-
- }
-
- }
-
- @EventHandler
- public void onClick(InventoryClickEvent event) {
-
- if (!SharedShopElements.inventoryNullPointerPreventer(event)) {
-
- return;
-
- }
-
- if (!event.getInventory().getName().equals(SHOP_NAME)) return;
-
- //reroll loot button
- if (event.getCurrentItem().getItemMeta().getDisplayName().equals(SignatureItem.SIGNATURE_ITEMSTACK.getItemMeta().getDisplayName())) {
-
- populateShop(event.getInventory());
- event.setCancelled(true);
- return;
-
- }
-
- if (!ObfuscatedSignatureLoreData.obfuscatedSignatureDetector(event.getCurrentItem())) {
-
- event.setCancelled(true);
- return;
-
- }
-
- Player player = (Player) event.getWhoClicked();
- ItemStack itemStack = event.getCurrentItem();
- String itemDisplayName = event.getCurrentItem().getItemMeta().getDisplayName();
-
- double itemValue = ItemWorthCalculator.determineItemWorth(itemStack);
-
- //These slots are for buying items
- if (validSlots.contains(event.getSlot()) && event.getClickedInventory().getName().equalsIgnoreCase(SHOP_NAME)) {
-
- boolean inventoryHasFreeSlots = false;
- for (ItemStack iteratedStack : player.getInventory()) {
-
- if (iteratedStack == null) {
-
- inventoryHasFreeSlots = true;
- break;
-
- }
-
- }
-
- if (!inventoryHasFreeSlots) {
-
- player.sendMessage("Your inventory is full! You can't buy items until you get some free space.");
- player.closeInventory();
-
- } else if (EconomyHandler.checkCurrency(UUIDFilter.guessUUI(player.getName())) >= itemValue) {
- //player has enough money
- EconomyHandler.subtractCurrency(UUIDFilter.guessUUI(player.getName()), itemValue);
- player.getInventory().addItem(itemStack);
- populateShop(event.getInventory());
-
- SharedShopElements.buyMessage(player, itemDisplayName, itemValue);
-
- } else {
-
- player.closeInventory();
- SharedShopElements.insufficientFundsMessage(player, itemValue);
-
- }
-
- }
-
- event.setCancelled(true);
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/shops/ItemSaleEvent.java b/src/main/java/com/magmaguy/elitemobs/commands/shops/ItemSaleEvent.java
deleted file mode 100644
index 8d3845a43..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/shops/ItemSaleEvent.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands.shops;
-
-import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.economy.UUIDFilter;
-import com.magmaguy.elitemobs.items.ItemWorthCalculator;
-import com.magmaguy.elitemobs.items.ObfuscatedSignatureLoreData;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.ItemStack;
-
-public class ItemSaleEvent implements Listener {
-
- @EventHandler
- public void playerSellEvent(InventoryClickEvent event) {
-
- if (!SharedShopElements.sellInventoryNullPointerPreventer(event)) {
-
- return;
-
- }
-
- if (!event.getInventory().getName().equals(ShopHandler.SHOP_NAME) &&
- !event.getInventory().getName().equals(CustomShopHandler.SHOP_NAME)) {
-
- return;
-
- }
-
- if (event.getClickedInventory().getName().equals(ShopHandler.SHOP_NAME) ||
- event.getClickedInventory().getName().equals(CustomShopHandler.SHOP_NAME)) {
-
- return;
-
- }
-
- if (!ObfuscatedSignatureLoreData.obfuscatedSignatureDetector(event.getCurrentItem())) {
-
- event.setCancelled(true);
- return;
-
- }
-
- Player player = (Player) event.getWhoClicked();
- ItemStack itemStack = event.getCurrentItem();
- String itemDisplayName = itemStack.getItemMeta().getDisplayName();
-
- double amountDeduced = ItemWorthCalculator.determineResaleWorth(itemStack);
-
- EconomyHandler.addCurrency(UUIDFilter.guessUUI(player.getName()), amountDeduced);
-
- if (event.getCurrentItem().getAmount() == 1) {
-
- event.setCurrentItem(new ItemStack(Material.AIR));
-
- } else if (event.getCurrentItem().getAmount() > 1) {
-
- int newAmount = event.getCurrentItem().getAmount() - 1;
-
- event.getCurrentItem().setAmount(newAmount);
-
- }
-
- SharedShopElements.sellMessage(player, itemDisplayName, amountDeduced);
-
- }
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/shops/SharedShopElements.java b/src/main/java/com/magmaguy/elitemobs/commands/shops/SharedShopElements.java
deleted file mode 100644
index 9d9e7a128..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/shops/SharedShopElements.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands.shops;
-
-import com.magmaguy.elitemobs.MetadataHandler;
-import com.magmaguy.elitemobs.commands.guiconfig.SignatureItem;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.EconomySettingsConfig;
-import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.economy.UUIDFilter;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.scheduler.BukkitRunnable;
-
-public class SharedShopElements {
-
- public static void shopHeader(Inventory shopInventory) {
-
- ItemStack signature = SignatureItem.SIGNATURE_ITEMSTACK;
-
- shopInventory.setItem(ConfigValues.economyConfig.getInt(EconomySettingsConfig.SIGNATURE_ITEM_LOCATION_SHOPS), signature);
-
- }
-
- public static boolean inventoryNullPointerPreventer(InventoryClickEvent event) {
-
- //Check if economy is enabled
- if (!ConfigValues.economyConfig.getBoolean(EconomySettingsConfig.ENABLE_ECONOMY)) return false;
- //Check if current item is valid
- if (event.getCurrentItem() == null) return false;
- if (event.getCurrentItem().getType().equals(Material.AIR)) return false;
- if (event.getCurrentItem().getItemMeta() == null) return false;
- return event.getCurrentItem().getItemMeta().hasLore();
-
- }
-
- public static boolean sellInventoryNullPointerPreventer(InventoryClickEvent event) {
-
- //Check if economy is enabled
- if (!ConfigValues.economyConfig.getBoolean(EconomySettingsConfig.ENABLE_ECONOMY)) return false;
- //Check if current item is valid
- if (event.getCurrentItem() == null) return false;
- return !event.getCurrentItem().getType().equals(Material.AIR);
- }
-
- public static void buyMessage(Player player, String itemDisplayName, double itemValue) {
-
- new BukkitRunnable() {
-
- @Override
- public void run() {
-
- player.sendMessage(ChatColor.GREEN + "You have bought " + itemDisplayName + " for " + ChatColor.DARK_GREEN + itemValue + " " + ChatColor.GREEN + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME));
- player.sendMessage(ChatColor.GREEN + "You have " + ChatColor.DARK_GREEN + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(player.getName())) + " " + ChatColor.GREEN + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME));
-
- }
-
-
- }.runTaskLater(Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS), 2);
-
- }
-
- public static void insufficientFundsMessage(Player player, double itemValue) {
-
- new BukkitRunnable() {
-
- @Override
- public void run() {
-
- player.sendMessage(ChatColor.RED + "You don't have enough " + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME) + "!");
- player.sendMessage(ChatColor.GREEN + "You have " + ChatColor.DARK_GREEN + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(player.getName())) + " " + ChatColor.GREEN + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME));
- player.sendMessage(ChatColor.GREEN + "That item cost " + ChatColor.DARK_GREEN + itemValue + " " + ChatColor.GREEN + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME) + ".");
-
- }
-
-
- }.runTaskLater(Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS), 2);
-
- player.closeInventory();
-
- }
-
- public static void sellMessage(Player player, String itemDisplayName, double amountDeduced) {
-
- player.sendMessage("You have sold " + itemDisplayName + " for " + amountDeduced + " " + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME));
-
- new BukkitRunnable() {
-
- @Override
- public void run() {
-
- player.sendMessage("You have " + EconomyHandler.checkCurrency(UUIDFilter.guessUUI(player.getName())) + " " + ConfigValues.economyConfig.getString(EconomySettingsConfig.CURRENCY_NAME));
-
- }
-
-
- }.runTaskLater(Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS), 2);
-
- }
-
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/commands/shops/ShopHandler.java b/src/main/java/com/magmaguy/elitemobs/commands/shops/ShopHandler.java
deleted file mode 100644
index 10b24e2e3..000000000
--- a/src/main/java/com/magmaguy/elitemobs/commands/shops/ShopHandler.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.commands.shops;
-
-import com.magmaguy.elitemobs.commands.guiconfig.SignatureItem;
-import com.magmaguy.elitemobs.config.ConfigValues;
-import com.magmaguy.elitemobs.config.EconomySettingsConfig;
-import com.magmaguy.elitemobs.economy.EconomyHandler;
-import com.magmaguy.elitemobs.economy.UUIDFilter;
-import com.magmaguy.elitemobs.items.ItemWorthCalculator;
-import com.magmaguy.elitemobs.items.ObfuscatedSignatureLoreData;
-import com.magmaguy.elitemobs.items.itemconstructor.ItemConstructor;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.Listener;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-
-import java.util.List;
-import java.util.Random;
-
-/**
- * Created by MagmaGuy on 17/06/2017.
- */
-public class ShopHandler implements Listener {
-
- public static final String SHOP_NAME = ConfigValues.economyConfig.getString(EconomySettingsConfig.SHOP_NAME);
-
- public void initializeShop(Player player) {
-
- Inventory shopInventory = Bukkit.createInventory(player, 54, SHOP_NAME);
-
- populateShop(shopInventory);
-
- player.openInventory(shopInventory);
-
- }
-
- private void populateShop(Inventory shopInventory) {
-
- SharedShopElements.shopHeader(shopInventory);
- shopContents(shopInventory);
-
- }
-
- private static List validSlots = (List) ConfigValues.economyConfig.getList(EconomySettingsConfig.SHOP_VALID_SLOTS);
-
- private void shopContents(Inventory shopInventory) {
-
- Random random = new Random();
-
- for (int i : validSlots) {
-
- int balancedMax = ConfigValues.economyConfig.getInt(EconomySettingsConfig.HIGHEST_PROCEDURALLY_SIMULATED_LOOT)
- - ConfigValues.economyConfig.getInt(EconomySettingsConfig.LOWEST_PROCEDURALLY_SIMULATED_LOOT);
- int balancedMin = ConfigValues.economyConfig.getInt(EconomySettingsConfig.LOWEST_PROCEDURALLY_SIMULATED_LOOT);
-
- int randomTier = random.nextInt(balancedMax) + balancedMin;
-
- shopInventory.setItem(i, ItemConstructor.constructItem(randomTier, null));
-
- }
-
- }
-
- @EventHandler
- public void onClick(InventoryClickEvent event) {
-
- if (!SharedShopElements.inventoryNullPointerPreventer(event))
- return;
-
- if (!event.getInventory().getName().equals(SHOP_NAME)) return;
-
- //reroll loot button
- if (event.getCurrentItem().getItemMeta().getDisplayName().equals(SignatureItem.SIGNATURE_ITEMSTACK.getItemMeta().getDisplayName())) {
-
- populateShop(event.getInventory());
- event.setCancelled(true);
- return;
-
- }
-
- if (!ObfuscatedSignatureLoreData.obfuscatedSignatureDetector(event.getCurrentItem())) {
-
- event.setCancelled(true);
- return;
-
- }
-
- Player player = (Player) event.getWhoClicked();
- ItemStack itemStack = event.getCurrentItem();
- String itemDisplayName = itemStack.getItemMeta().getDisplayName();
-
- double itemValue = ItemWorthCalculator.determineItemWorth(itemStack);
-
- boolean inventoryHasFreeSlots = false;
- for (ItemStack iteratedStack : player.getInventory().getStorageContents()) {
-
- if (iteratedStack == null) {
-
- inventoryHasFreeSlots = true;
- break;
-
- }
-
- }
-
- //These slots are for buying items
- if (event.getClickedInventory().getName().equalsIgnoreCase(SHOP_NAME) && validSlots.contains(event.getSlot())) {
-
- if (!inventoryHasFreeSlots) {
-
- player.sendMessage("Your inventory is full! You can't buy items until you get some free space.");
- player.closeInventory();
-
- } else if (EconomyHandler.checkCurrency(UUIDFilter.guessUUI(player.getName())) >= itemValue) {
- //player has enough money
- EconomyHandler.subtractCurrency(UUIDFilter.guessUUI(player.getName()), itemValue);
- player.getInventory().addItem(itemStack);
- populateShop(event.getInventory());
-
- SharedShopElements.buyMessage(player, itemDisplayName, itemValue);
-
- } else {
-
- player.closeInventory();
- SharedShopElements.insufficientFundsMessage(player, itemValue);
-
- }
-
- }
-
- event.setCancelled(true);
-
- }
-
-
-}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/AdventurersGuildConfig.java b/src/main/java/com/magmaguy/elitemobs/config/AdventurersGuildConfig.java
index 919bf63f8..7c38171bf 100644
--- a/src/main/java/com/magmaguy/elitemobs/config/AdventurersGuildConfig.java
+++ b/src/main/java/com/magmaguy/elitemobs/config/AdventurersGuildConfig.java
@@ -1,25 +1,481 @@
package com.magmaguy.elitemobs.config;
-import org.bukkit.configuration.Configuration;
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.commands.guild.AdventurersGuildCommand;
+import lombok.Getter;
+import lombok.Setter;
+import org.bukkit.Location;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
public class AdventurersGuildConfig {
+ @Getter
+ private static final String[][] rankNames = new String[11][21];
+ @Getter
+ private static final String[][] shortRankNames = new String[11][21];
+ @Getter
+ private static boolean addMaxHealth;
+ @Getter
+ private static boolean addCrit;
+ @Getter
+ private static boolean addDodge;
+ @Getter
+ private static boolean guildWorldIsEnabled;
+ @Getter
+ private static String guildWorldName;
+ @Getter
+ private static String guildLocationString;
+ @Getter
+ @Setter
+ private static Location guildWorldLocation;
+ @Getter
+ private static boolean agTeleport;
+ @Getter
+ private static boolean guildLootLimiter;
+ @Getter
+ private static String lootLimiterMessage;
+ @Getter
+ private static List onRankUpCommand;
+ @Getter
+ private static List onPrestigeUpCommand;
+ @Getter
+ private static double dodge1;
+ @Getter
+ private static double dodge2;
+ @Getter
+ private static double dodge3;
+ @Getter
+ private static double crit1;
+ @Getter
+ private static double crit2;
+ @Getter
+ private static double crit3;
+ @Getter
+ private static double health1;
+ @Getter
+ private static double health2;
+ @Getter
+ private static double health3;
+ @Getter
+ private static double health4;
+ @Getter
+ private static String adventurersGuildMenuName;
+ @Getter
+ private static int baseKillsForRankUp;
+ @Getter
+ private static int additionalKillsForRankUpPerTier;
+ @Getter
+ private static String prestigeUnlockMessageTitle;
+ @Getter
+ private static String prestigeUnlockMessageSubtitle;
+ @Getter
+ private static List worldsWithoutAGBonuses;
+ @Getter
+ private static double peacefulModeEliteChanceDecrease;
+
+ private static File file;
+ private static FileConfiguration fileConfiguration;
+
+ private AdventurersGuildConfig() {
+ }
+
+ public static void toggleGuildInstall() {
+ guildWorldIsEnabled = !guildWorldIsEnabled;
+ fileConfiguration.set("guildHubIsEnabledv2", guildWorldIsEnabled);
+ save();
+ }
+
+ public static void save() {
+ ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file);
+ }
+
+ public static void initializeConfig() {
+ file = ConfigurationEngine.fileCreator("AdventurersGuild.yml");
+ fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file);
+ addMaxHealth = ConfigurationEngine.setBoolean(fileConfiguration, "Add max health when unlocking higher guild ranks", true);
+ addCrit = ConfigurationEngine.setBoolean(fileConfiguration, "Add critical chance when unlocking higher guild ranks", true);
+ addDodge = ConfigurationEngine.setBoolean(fileConfiguration, "Add dodge chance when unlocking higher guild ranks", true);
+ guildWorldIsEnabled = ConfigurationEngine.setBoolean(fileConfiguration, "guildHubIsEnabledv2", false);
+ guildWorldName = ConfigurationEngine.setString(fileConfiguration, "Adventurer's Guild world name v3", "em_adventurers_guild");
+ guildLocationString = ConfigurationEngine.setString(fileConfiguration, "Guild world coordinates", "208.5,88,236.5,-80,0");
+ guildWorldLocation = null;
+ agTeleport = ConfigurationEngine.setBoolean(fileConfiguration, "userCommandsTeleportToAdventurersGuild", true);
+ adventurersGuildMenuName = ConfigurationEngine.setString(fileConfiguration, "adventurersGuildMenuName", "&6&lAdventurer's Hub");
+
+ //iterate through all prestige tiers
+ for (int prestigeRank = 0; prestigeRank < 11; prestigeRank++)
+ for (int normalRank = 0; normalRank < 11 + prestigeRank; normalRank++) {
+ String rankName = "";
+ String shortRankName = "";
+ switch (normalRank) {
+ case 0:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&8Commoner - disables elites!");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &8Commoner");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 1:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&fRookie");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &fRookie");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 2:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&fNovice");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &fNovice");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 3:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&fApprentice");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &fApprentice");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 4:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&2Adventurer");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &2Adventurer");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 5:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&2Journeyman");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &2Journeyman");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 6:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&2Adept");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &2Adept");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 7:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&1Veteran");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &1Veteran");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 8:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&1Elite");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &1Elite");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 9:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&lMaster");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Master");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 10:
+ if (prestigeRank == 0) {
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, "&5Hero");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", "&6&l✧&e" + romanNumerals(normalRank));
+ } else {
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Hero");
+ }
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 11:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Legend");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 12:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Myth");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 13:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Immortal");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 14:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Chosen");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 15:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Ascendant");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 16:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Titan");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 17:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Demigod");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 18:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Deity");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 19:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Godhunter");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ case 20:
+ rankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank, prestigeColors(prestigeRank) + "Prestige " + prestigeRank + " &5Godslayer");
+ shortRankName = ConfigurationEngine.setString(fileConfiguration,
+ "Prestige " + prestigeRank + " rank " + normalRank + " short placeholder", prestigeColors(prestigeRank) + "⚜" + romanNumerals(prestigeRank) + "&6&l✧&e" + romanNumerals(normalRank));
+ rankNames[prestigeRank][normalRank] = rankName;
+ shortRankNames[prestigeRank][normalRank] = shortRankName;
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + normalRank);
+ }
- public static final String CONFIG_NAME = "AdventurersGuild.yml";
+ }
- public static final String ENABLE_ADVENTURERS_GUILD = "Enable adventurer's guild";
+ guildLootLimiter = ConfigurationEngine.setBoolean(fileConfiguration, "limitLootBasedOnGuildTier", true);
+ lootLimiterMessage = ConfigurationEngine.setString(fileConfiguration, "lootLimiterMessage", "&7[EM] &cYou must unlock the next guild rank through /ag to loot better items!");
+ onRankUpCommand = ConfigurationEngine.setList(fileConfiguration, "onRankUpCommand", Collections.emptyList());
+ onPrestigeUpCommand = ConfigurationEngine.setList(fileConfiguration, "onPrestigeUpCommand", Collections.emptyList());
+ dodge1 = ConfigurationEngine.setDouble(fileConfiguration, "dodgePrestige3Bonus", 3);
+ dodge2 = ConfigurationEngine.setDouble(fileConfiguration, "dodgePrestige6Bonus", 6);
+ dodge3 = ConfigurationEngine.setDouble(fileConfiguration, "dodgePrestige9Bonus", 10);
+ crit1 = ConfigurationEngine.setDouble(fileConfiguration, "critPrestige2Bonus", 3);
+ crit2 = ConfigurationEngine.setDouble(fileConfiguration, "critPrestige5Bonus", 6);
+ crit3 = ConfigurationEngine.setDouble(fileConfiguration, "critPrestige8Bonus", 10);
+ health1 = ConfigurationEngine.setDouble(fileConfiguration, "healthPrestige1Bonus", 2);
+ health2 = ConfigurationEngine.setDouble(fileConfiguration, "healthPrestige4Bonus", 2.5);
+ health3 = ConfigurationEngine.setDouble(fileConfiguration, "healthPrestige7Bonus", 3);
+ health4 = ConfigurationEngine.setDouble(fileConfiguration, "healthPrestige10Bonus", 4);
- CustomConfigLoader customConfigLoader = new CustomConfigLoader();
- Configuration configuration = customConfigLoader.getCustomConfig(CONFIG_NAME);
+ baseKillsForRankUp = ConfigurationEngine.setInt(fileConfiguration, "baseKillsForRankUp", 100);
+ additionalKillsForRankUpPerTier = ConfigurationEngine.setInt(fileConfiguration, "additionalKillsForRankUpPerTier", 50);
- public void initializeConfig(){
+ prestigeUnlockMessageTitle = ConfigurationEngine.setString(fileConfiguration, "prestigeUnlockMessageTitle", "$player");
+ prestigeUnlockMessageSubtitle = ConfigurationEngine.setString(fileConfiguration, "prestigeUnlockMessageSubtitle", "&2has unlocked $tier&2!");
- configuration.addDefault(ENABLE_ADVENTURERS_GUILD, true);
+ //initializes the AG location
+ AdventurersGuildCommand.defineTeleportLocation();
- configuration.options().copyDefaults(true);
- UnusedNodeHandler.clearNodes(configuration);
- customConfigLoader.saveDefaultCustomConfig(CONFIG_NAME);
- customConfigLoader.saveCustomConfig(CONFIG_NAME);
+ peacefulModeEliteChanceDecrease = ConfigurationEngine.setDouble(fileConfiguration, "peacefulModeEliteChanceDecrease", 0.2);
+
+ worldsWithoutAGBonuses = ConfigurationEngine.setList(fileConfiguration, "worldsWithoutAGBonuses", new ArrayList());
+
+ save();
+ }
+
+ public static String getRankName(int prestigeTier, int rankTier) {
+ return ChatColorConverter.convert(rankNames[prestigeTier][rankTier]);
+ }
+
+ public static String getShortenedRankName(int prestigeTier, int rankTier) {
+ return ChatColorConverter.convert(shortRankNames[prestigeTier][rankTier]);
+ }
+
+ private static String prestigeColors(int prestigeTier) {
+ switch (prestigeTier) {
+ case 1:
+ return "&e";
+ case 2:
+ return "&2";
+ case 3:
+ return "&a";
+ case 4:
+ return "&3";
+ case 5:
+ return "&b";
+ case 6:
+ return "&4";
+ case 7:
+ return "&c";
+ case 8:
+ return "&9";
+ case 9:
+ return "&d";
+ case 10:
+ return "&5";
+ default:
+ return "error";
+ }
+ }
+ private static String romanNumerals(int prestigeTier) {
+ switch (prestigeTier) {
+ case 1:
+ return "Ⅰ";
+ case 2:
+ return "ⅠⅠ";
+ case 3:
+ return "ⅠⅠⅠ";
+ case 4:
+ return "ⅠⅤ";
+ case 5:
+ return "Ⅴ";
+ case 6:
+ return "ⅤⅠ";
+ case 7:
+ return "ⅤⅠⅠ";
+ case 8:
+ return "ⅤⅠⅠⅠ";
+ case 9:
+ return "ⅠⅩ";
+ case 10:
+ return "Ⅹ";
+ case 11:
+ return "ⅩⅠ";
+ case 12:
+ return "ⅩⅠⅠ";
+ case 13:
+ return "ⅩⅠⅠⅠ";
+ case 14:
+ return "ⅩⅠⅤ";
+ case 15:
+ return "ⅩⅤ";
+ case 16:
+ return "ⅩⅤⅠ";
+ case 17:
+ return "ⅩⅤⅠⅠ";
+ case 18:
+ return "ⅩⅤⅠⅠⅠ";
+ case 19:
+ return "ⅩⅠⅩ";
+ case 20:
+ return "ⅩⅩ";
+ case 0:
+ return "0";
+ default:
+ return "error";
+ }
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/AntiExploitConfig.java b/src/main/java/com/magmaguy/elitemobs/config/AntiExploitConfig.java
new file mode 100644
index 000000000..df4839830
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/AntiExploitConfig.java
@@ -0,0 +1,64 @@
+package com.magmaguy.elitemobs.config;
+
+import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.io.File;
+
+public class AntiExploitConfig {
+ @Getter
+ private static String antiExploitMessage;
+ @Getter
+ private static boolean darkroomAntiExploit1;
+ @Getter
+ private static boolean darkroomAntiExploit2;
+ @Getter
+ private static boolean darkroomAntiExploit3;
+ @Getter
+ private static boolean largeDarkroomAntiExploit1;
+ @Getter
+ private static boolean largeDarkroomAntiExploit2;
+ @Getter
+ private static boolean largeDarkroomAntiExploit3;
+ @Getter
+ private static boolean endermanHeightAntiExploit;
+ @Getter
+ private static boolean mountAntiExploit;
+ @Getter
+ private static boolean towerAntiExploit;
+ @Getter
+ private static boolean ambientDamageExploit;
+ @Getter
+ private static boolean honeyBlockExploit;
+ @Getter
+ private static boolean noItemPickup;
+ @Getter
+ private static int antiExploitThreshold;
+
+ private AntiExploitConfig() {
+ }
+
+ public static void initializeConfig() {
+ File file = ConfigurationEngine.fileCreator("AntiExploit.yml");
+ FileConfiguration fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file);
+
+ antiExploitMessage = ConfigurationEngine.setString(fileConfiguration, "AntiExploit message",
+ "&c[EM AntiExploit] &7Nearby elite won't drop special loot.");
+ darkroomAntiExploit1 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable darkroom antiexploit 1", true);
+ darkroomAntiExploit2 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable darkroom antiexploit 2", true);
+ darkroomAntiExploit3 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable darkroom antiexploit 3", true);
+ largeDarkroomAntiExploit1 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable large darkroom antiexploit 1", true);
+ largeDarkroomAntiExploit2 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable large darkroom antiexploit 2", true);
+ largeDarkroomAntiExploit3 = ConfigurationEngine.setBoolean(fileConfiguration, "Enable large darkroom antiexploit 3", true);
+ endermanHeightAntiExploit = ConfigurationEngine.setBoolean(fileConfiguration, "Enable enderman height antiexploit", true);
+ mountAntiExploit = ConfigurationEngine.setBoolean(fileConfiguration, "Enable mount antiexploit", true);
+ towerAntiExploit = ConfigurationEngine.setBoolean(fileConfiguration, "Enable tower antiexploit", true);
+ noItemPickup = ConfigurationEngine.setBoolean(fileConfiguration, "preventItemPickupByMobs", true);
+ ambientDamageExploit = ConfigurationEngine.setBoolean(fileConfiguration, "Enable ambient damage antiexploit", true);
+ honeyBlockExploit = ConfigurationEngine.setBoolean(fileConfiguration, "Enable honey block antiexploit", true);
+ antiExploitThreshold = ConfigurationEngine.setInt(fileConfiguration, "antiExploitThreshold", 10);
+
+ ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/ArenasConfig.java b/src/main/java/com/magmaguy/elitemobs/config/ArenasConfig.java
new file mode 100644
index 000000000..eaff03bf6
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/ArenasConfig.java
@@ -0,0 +1,79 @@
+package com.magmaguy.elitemobs.config;
+
+import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.io.File;
+
+public class ArenasConfig {
+ @Getter
+ private static String notEnoughPlayersMessage;
+ @Getter
+ private static String startingTitle;
+ @Getter
+ private static String startingSubtitle;
+ @Getter
+ private static String arenaFullMessage;
+ @Getter
+ private static String arenasOngoingMessage;
+ @Getter
+ private static String arenaStartHintMessage;
+ @Getter
+ private static String arenaQuitHintMessage;
+ @Getter
+ private static String arenaJoinPlayerMessage;
+ @Getter
+ private static String arenaJoinSpectatorMessage;
+ @Getter
+ private static String waveTitle;
+ @Getter
+ private static String waveSubtitle;
+ @Getter
+ private static String victoryTitle;
+ @Getter
+ private static String victorySubtitle;
+ @Getter
+ private static String defeatTitle;
+ @Getter
+ private static String defeatSubtitle;
+ @Getter
+ private static String victoryBroadcast;
+ @Getter
+ private static String joinPlayerTitle;
+ @Getter
+ private static String joinPlayerSubtitle;
+ @Getter
+ private static String joinSpectatorTitle;
+ @Getter
+ private static String joinSpectatorSubtitle;
+
+ private ArenasConfig() {
+ }
+
+ public static void initializeConfig() {
+ File file = ConfigurationEngine.fileCreator("Arenas.yml");
+ FileConfiguration fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file);
+
+ notEnoughPlayersMessage = ConfigurationEngine.setString(fileConfiguration, "notEnoughPlayersMessage", "&8[EliteMobs] &cYou need at least $amount to start the match!");
+ startingTitle = ConfigurationEngine.setString(fileConfiguration, "startingMessage", "&2Starting!");
+ startingSubtitle = ConfigurationEngine.setString(fileConfiguration, "startingSubtitle", "&2in $count...");
+ arenaFullMessage = ConfigurationEngine.setString(fileConfiguration, "arenaFullMessage", "&4[EliteMobs] &cArena is full! You can spectate instead while you wait for it to finish!");
+ arenasOngoingMessage = ConfigurationEngine.setString(fileConfiguration, "arenasOngoingMessage", "&4[EliteMobs] &cCan't join the arena now - a match is currently happening! You can spectate instead while you wait for it to finish!");
+ arenaStartHintMessage = ConfigurationEngine.setString(fileConfiguration, "arenaStartHintMessage", "&2[EliteMobs] &aYou can start the arena by doing &2/em start");
+ arenaQuitHintMessage = ConfigurationEngine.setString(fileConfiguration, "arenaQuitHintMessage", "&4[EliteMobs] &cYou can leave the arena by doing &4/em quit");
+ arenaJoinPlayerMessage = ConfigurationEngine.setString(fileConfiguration, "arenaJoinPlayerMessage", "&2[EliteMobs] &aYou can start the arena by doing &2/em start &aif there are at least &2$count &aplayers in it! \nYou can leave the arena by doing &c/em quit");
+ arenaJoinSpectatorMessage = ConfigurationEngine.setString(fileConfiguration, "arenaJoinSpectatorMessage", "&2[EliteMobs] &aYou can leave the arena at any time using &2/em quit");
+ waveTitle = ConfigurationEngine.setString(fileConfiguration, "waveTitle", "&aWave &2$wave");
+ waveSubtitle = ConfigurationEngine.setString(fileConfiguration, "waveSubtitle", "");
+ victoryTitle = ConfigurationEngine.setString(fileConfiguration, "victoryTitle", "&2Victory!");
+ victorySubtitle = ConfigurationEngine.setString(fileConfiguration, "victorySubtitle", "&aCompleted &2$wave &awaves!");
+ defeatTitle = ConfigurationEngine.setString(fileConfiguration, "defeatTitle", "&4Defeat!");
+ defeatSubtitle = ConfigurationEngine.setString(fileConfiguration, "defeatSubtitle", "&cReached wave &4$wave&c!");
+ victoryBroadcast = ConfigurationEngine.setString(fileConfiguration, "victoryBroadcast", "Arena $arenaName was conquered by $players!");
+ joinPlayerTitle = ConfigurationEngine.setString(fileConfiguration, "joinPlayerTitle", "&aStart with &2/em start &a!");
+ joinPlayerSubtitle = ConfigurationEngine.setString(fileConfiguration, "joinPlayerSubtitle", "&cLeave with &4/em quit &c!");
+ joinSpectatorTitle = ConfigurationEngine.setString(fileConfiguration, "joinSpectatorTitle", "&aNow spectating!");
+ joinSpectatorSubtitle = ConfigurationEngine.setString(fileConfiguration, "joinSpectatorSubtitle", "&cLeave with &4/em quit &c!");
+ ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file);
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/CombatTagConfig.java b/src/main/java/com/magmaguy/elitemobs/config/CombatTagConfig.java
index dc84f734c..6749d5195 100644
--- a/src/main/java/com/magmaguy/elitemobs/config/CombatTagConfig.java
+++ b/src/main/java/com/magmaguy/elitemobs/config/CombatTagConfig.java
@@ -1,27 +1,30 @@
package com.magmaguy.elitemobs.config;
-import org.bukkit.configuration.Configuration;
+import lombok.Getter;
+import org.bukkit.configuration.file.FileConfiguration;
-public class CombatTagConfig {
-
- public static final String CONFIG_NAME = "CombatTag.yml";
-
- public static final String ENABLE_COMBAT_TAG = "Enable combat tag";
- public static final String COMBAT_TAG_MESSAGE = "Combat tag message";
+import java.io.File;
- CustomConfigLoader customConfigLoader = new CustomConfigLoader();
- private Configuration configuration = customConfigLoader.getCustomConfig(CONFIG_NAME);
-
- public void initializeConfig(){
+public class CombatTagConfig {
+ @Getter
+ private static boolean enableCombatTag;
+ @Getter
+ private static String combatTagMessage;
+ @Getter
+ private static boolean enableTeleportTimer;
+
+ private CombatTagConfig() {
+ }
- configuration.addDefault(ENABLE_COMBAT_TAG, true);
- configuration.addDefault(COMBAT_TAG_MESSAGE, "&c[EliteMobs] Combat tag activated!");
+ public static void initializeConfig() {
+ File file = ConfigurationEngine.fileCreator("CombatTag.yml");
+ FileConfiguration fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file);
- customConfigLoader.getCustomConfig(CONFIG_NAME).options().copyDefaults(true);
- UnusedNodeHandler.clearNodes(configuration);
- customConfigLoader.saveDefaultCustomConfig(CONFIG_NAME);
- customConfigLoader.saveCustomConfig(CONFIG_NAME);
+ enableCombatTag = ConfigurationEngine.setBoolean(fileConfiguration, "Enable combat tag", true);
+ combatTagMessage = ConfigurationEngine.setString(fileConfiguration, "Combat tag message", "&c[EliteMobs] Combat tag activated!");
+ enableTeleportTimer = ConfigurationEngine.setBoolean(fileConfiguration, "Enable adventurers guild teleport timer", true);
+ ConfigurationEngine.fileSaverOnlyDefaults(fileConfiguration, file);
}
}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigValues.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigValues.java
deleted file mode 100644
index 68a35cd75..000000000
--- a/src/main/java/com/magmaguy/elitemobs/config/ConfigValues.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.config;
-
-import com.magmaguy.elitemobs.MetadataHandler;
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.Configuration;
-
-/**
- * Created by MagmaGuy on 05/05/2017.
- */
-public class ConfigValues {
-
- public static Configuration defaultConfig, itemsCustomLootListConfig, mobPowerConfig, translationConfig,
- itemsProceduralSettingsConfig, economyConfig, playerCacheConfig, eventsConfig, itemsCustomLootSettingsConfig,
- validMobsConfig, validWorldsConfig, itemsUniqueConfig, mobCombatSettingsConfig, itemsDropSettingsConfig,
- playerMoneyData, playerRankData, playerMaxRankData, combatTagConfig, adventurersGuildConfig,
- customEnchantmentsConfig;
-
- public static void initializeCachedConfigurations() {
-
- CustomConfigLoader customConfigLoader = new CustomConfigLoader();
-
- defaultConfig = Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS).getConfig();
-
- customConfigLoader = new CustomConfigLoader();
- itemsCustomLootListConfig = customConfigLoader.getCustomConfig(ItemsCustomLootListConfig.CONFIG_NAME, true);
-
- customConfigLoader = new CustomConfigLoader();
- mobPowerConfig = customConfigLoader.getCustomConfig(MobPowersConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- itemsCustomLootSettingsConfig = customConfigLoader.getCustomConfig(ItemsCustomLootSettingsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- translationConfig = customConfigLoader.getCustomConfig(TranslationConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- itemsProceduralSettingsConfig = customConfigLoader.getCustomConfig(ItemsProceduralSettingsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- economyConfig = customConfigLoader.getCustomConfig(EconomySettingsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- playerCacheConfig = customConfigLoader.getCustomConfig(PlayerCacheData.CONFIG_NAME, true);
-
- customConfigLoader = new CustomConfigLoader();
- playerMoneyData = customConfigLoader.getCustomConfig(PlayerMoneyData.CONFIG_NAME, true);
-
- customConfigLoader = new CustomConfigLoader();
- playerRankData = customConfigLoader.getCustomConfig(PlayerGuildRank.CONFIG_NAME, true);
-
- customConfigLoader = new CustomConfigLoader();
- playerMaxRankData = customConfigLoader.getCustomConfig(PlayerMaxGuildRank.CONFIG_NAME, true);
-
- customConfigLoader = new CustomConfigLoader();
- eventsConfig = customConfigLoader.getCustomConfig(EventsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- validMobsConfig = customConfigLoader.getCustomConfig(ValidMobsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- validWorldsConfig = customConfigLoader.getCustomConfig(ValidWorldsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- itemsUniqueConfig = customConfigLoader.getCustomConfig(ItemsUniqueConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- mobCombatSettingsConfig = customConfigLoader.getCustomConfig(MobCombatSettingsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- itemsDropSettingsConfig = customConfigLoader.getCustomConfig(ItemsDropSettingsConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- combatTagConfig = customConfigLoader.getCustomConfig(CombatTagConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- adventurersGuildConfig = customConfigLoader.getCustomConfig(AdventurersGuildConfig.CONFIG_NAME);
-
- customConfigLoader = new CustomConfigLoader();
- customEnchantmentsConfig = customConfigLoader.getCustomConfig(CustomEnchantmentsConfig.CONFIG_NAME);
-
- }
-
- public static void intializeConfigurations() {
-
- DefaultConfig defaultConfig = new DefaultConfig();
- defaultConfig.loadConfiguration();
-
- MobPowersConfig mobPowersConfig = new MobPowersConfig();
- mobPowersConfig.initializeConfig();
-
- ItemsCustomLootListConfig itemsCustomLootListConfig = new ItemsCustomLootListConfig();
- itemsCustomLootListConfig.intializeConfig();
-
- ItemsCustomLootSettingsConfig itemsCustomLootSettingsConfig = new ItemsCustomLootSettingsConfig();
- itemsCustomLootSettingsConfig.initializeConfig();
-
- TranslationConfig translationConfig = new TranslationConfig();
- translationConfig.initializeConfig();
-
- ItemsProceduralSettingsConfig itemsProceduralSettingsConfig = new ItemsProceduralSettingsConfig();
- itemsProceduralSettingsConfig.intializeConfig();
-
- EconomySettingsConfig economySettingsConfig = new EconomySettingsConfig();
- economySettingsConfig.initializeConfig();
-
- PlayerMoneyData playerMoneyData = new PlayerMoneyData();
- playerMoneyData.intializeConfig();
-
- PlayerCacheData playerCacheData = new PlayerCacheData();
- playerCacheData.initializeConfig();
-
- EventsConfig eventsConfig = new EventsConfig();
- eventsConfig.initializeConfig();
-
- ValidWorldsConfig validWorldsConfig = new ValidWorldsConfig();
- validWorldsConfig.initializeConfig();
-
- ValidMobsConfig validMobsConfig = new ValidMobsConfig();
- validMobsConfig.initializeConfig();
-
- ItemsUniqueConfig itemsUniqueConfig = new ItemsUniqueConfig();
- itemsUniqueConfig.initializeConfig();
-
- MobCombatSettingsConfig mobCombatSettingsConfig = new MobCombatSettingsConfig();
- mobCombatSettingsConfig.initializeConfig();
-
- ItemsDropSettingsConfig itemsDropSettingsConfig = new ItemsDropSettingsConfig();
- itemsDropSettingsConfig.initializeConfig();
-
- PlayerGuildRank playerGuildRank = new PlayerGuildRank();
- playerGuildRank.intializeConfig();
-
- PlayerMaxGuildRank playerMaxGuildRank = new PlayerMaxGuildRank();
- playerMaxGuildRank.intializeConfig();
-
- CombatTagConfig combatTagConfig = new CombatTagConfig();
- combatTagConfig.initializeConfig();
-
- AdventurersGuildConfig adventurersGuildConfig = new AdventurersGuildConfig();
- adventurersGuildConfig.initializeConfig();
-
- CustomEnchantmentsConfig customEnchantmentsConfig = new CustomEnchantmentsConfig();
- customEnchantmentsConfig.initializeConfig();
-
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationEngine.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationEngine.java
new file mode 100644
index 000000000..fbed738db
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationEngine.java
@@ -0,0 +1,145 @@
+package com.magmaguy.elitemobs.config;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.utils.ItemStackGenerator;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.SkullMeta;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ConfigurationEngine {
+
+ public static File fileCreator(String path, String fileName) {
+ File file = new File(MetadataHandler.PLUGIN.getDataFolder().getPath() + "/" + path + "/", fileName);
+ return fileCreator(file);
+ }
+
+ public static File fileCreator(String fileName) {
+ File file = new File(MetadataHandler.PLUGIN.getDataFolder().getPath(), fileName);
+ return fileCreator(file);
+ }
+
+ public static File fileCreator(File file) {
+
+ if (!file.exists())
+ try {
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+ } catch (IOException ex) {
+ Bukkit.getLogger().warning("[EliteMobs] Error generating the plugin file: " + file.getName());
+ }
+
+ return file;
+
+ }
+
+ public static FileConfiguration fileConfigurationCreator(File file) {
+ return YamlConfiguration.loadConfiguration(file);
+ }
+
+ public static void fileSaverCustomValues(FileConfiguration fileConfiguration, File file) {
+ fileConfiguration.options().copyDefaults(true);
+
+ try {
+ fileConfiguration.save(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public static void fileSaverOnlyDefaults(FileConfiguration fileConfiguration, File file) {
+ fileConfiguration.options().copyDefaults(true);
+ UnusedNodeHandler.clearNodes(fileConfiguration);
+
+ try {
+ fileConfiguration.save(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public static Boolean setBoolean(FileConfiguration fileConfiguration, String key, boolean defaultValue) {
+ fileConfiguration.addDefault(key, defaultValue);
+ return fileConfiguration.getBoolean(key);
+ }
+
+ public static String setString(FileConfiguration fileConfiguration, String key, String defaultValue) {
+ fileConfiguration.addDefault(key, defaultValue);
+ return ChatColorConverter.convert(fileConfiguration.getString(key));
+ }
+
+ public static int setInt(FileConfiguration fileConfiguration, String key, int defaultValue) {
+ fileConfiguration.addDefault(key, defaultValue);
+ return fileConfiguration.getInt(key);
+ }
+
+ public static double setDouble(FileConfiguration fileConfiguration, String key, double defaultValue) {
+ fileConfiguration.addDefault(key, defaultValue);
+ return fileConfiguration.getDouble(key);
+ }
+
+ public static List setList(FileConfiguration fileConfiguration, String key, List defaultValue) {
+ fileConfiguration.addDefault(key, defaultValue);
+ return fileConfiguration.getList(key);
+ }
+
+ public static ItemStack setItemStack(FileConfiguration fileConfiguration, String key, ItemStack itemStack) {
+ fileConfiguration.addDefault(key + ".material", itemStack.getType().toString());
+ if (itemStack.hasItemMeta() && itemStack.getItemMeta().hasDisplayName())
+ fileConfiguration.addDefault(key + ".name", itemStack.getItemMeta().getDisplayName());
+ if (itemStack.hasItemMeta() && itemStack.getItemMeta().hasLore())
+ fileConfiguration.addDefault(key + ".lore", itemStack.getItemMeta().getLore());
+ if (itemStack.getType().equals(Material.PLAYER_HEAD))
+ fileConfiguration.addDefault(key + ".owner", ((SkullMeta) itemStack.getItemMeta()).getOwner());
+ Material material;
+ try {
+ material = Material.valueOf(fileConfiguration.getString(key + ".material"));
+ } catch (Exception ex) {
+ new WarningMessage("Material type " + fileConfiguration.getString(key + ".material") + " is not valid! Correct it to make a valid item.");
+ return null;
+ }
+ String name = "";
+ try {
+ name = fileConfiguration.getString(key + ".name");
+ } catch (Exception ex) {
+ new WarningMessage("Item name " + fileConfiguration.getString(key + ".name") + " is not valid! Correct it to make a valid item.");
+ }
+ List lore = new ArrayList<>();
+ try {
+ lore = fileConfiguration.getStringList(key + ".lore");
+ } catch (Exception ex) {
+ new WarningMessage("Item lore " + fileConfiguration.getString(key + ".lore") + " is not valid! Correct it to make a valid item.");
+ }
+ ItemStack fileItemStack = ItemStackGenerator.generateItemStack(material, name, lore);
+ if (material == Material.PLAYER_HEAD)
+ ((SkullMeta) itemStack.getItemMeta()).setOwningPlayer(Bukkit.getOfflinePlayer(fileConfiguration.getString(key + ".owner")));
+ return fileItemStack;
+ }
+
+ public static boolean writeValue(Object value, File file, FileConfiguration fileConfiguration, String path) {
+ fileConfiguration.set(path, value);
+ try {
+ fileSaverCustomValues(fileConfiguration, file);
+ } catch (Exception exception) {
+ new WarningMessage("Failed to write value for " + path + " in file " + file.getName());
+ return false;
+ }
+ return true;
+ }
+
+ public static void removeValue(File file, FileConfiguration fileConfiguration, String path) {
+ writeValue(null, file, fileConfiguration, path);
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java
new file mode 100644
index 000000000..63995aee9
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java
@@ -0,0 +1,209 @@
+package com.magmaguy.elitemobs.config;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.utils.InfoMessage;
+import com.magmaguy.elitemobs.utils.SpigotMessage;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import com.magmaguy.elitemobs.utils.ZipFile;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Properties;
+
+public class ConfigurationExporter {
+ private ConfigurationExporter() {
+ }
+
+ public static void initializeConfigs() {
+ Path configurationsPath = Paths.get(MetadataHandler.PLUGIN.getDataFolder().getAbsolutePath());
+ if (!Files.isDirectory(Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "exports"))) {
+ try {
+ Files.createDirectory(Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "exports"));
+ } catch (Exception exception) {
+ new WarningMessage("Failed to create exports directory! Tell the dev!");
+ exception.printStackTrace();
+ }
+ return;
+ }
+
+ try {
+ new File(Paths.get(MetadataHandler.PLUGIN.getDataFolder().getCanonicalPath() + File.separatorChar + "exports").toString());
+ } catch (Exception ex) {
+ new WarningMessage("Failed to get imports folder! Report this to the dev!");
+ }
+
+ }
+
+ public static void createResourcePack(CommandSender commandSender) {
+ if (!Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Could not generate resource pack because ModelEngine is not installed! Install ModelEngine to use this feature."));
+ return;
+ }
+
+ File modelEngineResourcePackFile = new File(MetadataHandler.PLUGIN.getDataFolder().getParentFile().toString() + File.separatorChar + "ModelEngine" + File.separatorChar + "resource pack");
+ if (!modelEngineResourcePackFile.exists()) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Could not generate resource pack because ModelEngine is not installed! Install ModelEngine to use this feature."));
+ return;
+ }
+
+
+ try {
+ if (!Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack").toFile().exists())
+ Files.createDirectory(Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"));
+ } catch (Exception ex) {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Failed to generate target directory plugins/EliteMobs/exports/elitemobs_resource_pack required for storing the resource pack! Report this to the dev!"));
+ return;
+ }
+
+ copyDirectory(modelEngineResourcePackFile, Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"));
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Copied all files from Model Engine to " + MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"));
+
+ if (ZipFile.zip(new File(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"),
+ MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip"))
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Packaged texture pack into " +
+ MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip") +
+ " , ready to distribute!");
+ else {
+ commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Failed to package the resource pack into a zipped file! Report this to the dev!"));
+ return;
+ }
+
+ if (commandSender instanceof Player) {
+ ((Player) commandSender).spigot().sendMessage(SpigotMessage.commandHoverMessage(ChatColorConverter.convert("Done! &2You can click here to update your server.properties with the new SHA1 value of this texture pack!"),
+ "Click runs the /em updateresourcepack command!", "/em updateresourcepack"));
+ commandSender.sendMessage("If you want to do it manually, your SHA1 code is " + generateResourcePackSHA1(commandSender));
+ } else {
+ commandSender.sendMessage("Done! You can run the command /em updateresourcepack in order to put the right SHA1 value into server.properties. Don't forget to upload the texture place to some place where players can get it!");
+ commandSender.sendMessage("If you want to do it manually, your SHA1 code is " + generateResourcePackSHA1(commandSender));
+ }
+
+ }
+
+ private static String generateResourcePackSHA1(CommandSender commandSender) {
+ File zippedResourcePack = Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip").toFile();
+ if (!zippedResourcePack.exists()) {
+ commandSender.sendMessage("[EliteMobs] Failed to generate SHA-1 code, no zipped resource pack found!");
+ return null;
+ }
+ String sha1 = null;
+ try {
+ sha1 = sha1Code(zippedResourcePack);
+ } catch (Exception ex) {
+ commandSender.sendMessage("[EliteMobs] Failed to generate SHA-1 code! Report this to the dev!");
+ ex.printStackTrace();
+ return null;
+ }
+ if (sha1 == null) {
+ commandSender.sendMessage("[EliteMobs] SHA-1 code is null! Report this to the dev!");
+ return null;
+ }
+ return sha1;
+ }
+
+ public static String sha1Code(File file) throws IOException, NoSuchAlgorithmException {
+ FileInputStream fileInputStream = new FileInputStream(file);
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ DigestInputStream digestInputStream = new DigestInputStream(fileInputStream, digest);
+ byte[] bytes = new byte[1024];
+ // read all file content
+ while (digestInputStream.read(bytes) > 0)
+ digest = digestInputStream.getMessageDigest();
+ byte[] resultByteArry = digest.digest();
+ return bytesToHexString(resultByteArry);
+ }
+
+ public static String bytesToHexString(byte[] bytes) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ int value = b & 0xFF;
+ if (value < 16) {
+ // if value less than 16, then it's hex String will be only
+ // one character, so we need to append a character of '0'
+ sb.append("0");
+ }
+ sb.append(Integer.toHexString(value).toUpperCase());
+ }
+ return sb.toString();
+ }
+
+ private static void copyDirectory(File directoryToClone, Path targetPath) {
+ for (File file : directoryToClone.listFiles())
+ try {
+ new InfoMessage("Adding " + file.getCanonicalPath());
+ copyFile(file, targetPath);
+ } catch (Exception exception) {
+ new WarningMessage("Failed to move directories for " + file.getName() + "! Tell the dev!");
+ exception.printStackTrace();
+ }
+ }
+
+ private static void copyFile(File file, Path targetPath) {
+ try {
+ if (file.isDirectory()) {
+ if (!Paths.get(targetPath + "" + File.separatorChar + file.getName()).toFile().exists())
+ Files.createDirectory(Paths.get(targetPath + "" + File.separatorChar + file.getName()));
+ for (File iteratedFile : file.listFiles())
+ copyFile(iteratedFile, Paths.get(targetPath + "" + File.separatorChar + file.getName()));
+ } else {
+ if (!Paths.get(targetPath + "" + File.separatorChar + file.getName()).toFile().exists() ||
+ !targetPath.toString().contains("pack.png") && !targetPath.toString().contains("pack.mcmeta"))
+ Files.copy(file.toPath(), Paths.get(targetPath + "" + File.separatorChar + file.getName()), StandardCopyOption.REPLACE_EXISTING);
+ else
+ new InfoMessage("File " + targetPath + "" + File.separatorChar + file.getName() + " already existed and should not be overwritten, skipping!");
+ }
+ } catch (Exception exception) {
+ new WarningMessage("Failed to copy directories for " + file.getName() + "! Tell the dev!");
+ exception.printStackTrace();
+ }
+ }
+
+ public static void overwriteSHA1(CommandSender commandSender) {
+ File serverProperties = null;
+ try {
+ serverProperties = new File(Paths.get(MetadataHandler.PLUGIN.getDataFolder().getParentFile().getCanonicalFile().getParentFile().toString() + File.separatorChar + "server.properties").toString());
+ if (!serverProperties.exists()) {
+ commandSender.sendMessage("[EliteMobs] Could not find server.properties file correctly! You will have to set the SHA-1 value manually!");
+ return;
+ }
+ } catch (Exception exception) {
+ new WarningMessage("[EliteMobs] Could not find server.properties file correctly! You will have to set the SHA-1 value manually.");
+ exception.printStackTrace();
+ return;
+ }
+
+ String sha1 = generateResourcePackSHA1(commandSender);
+ if (sha1 == null) return;
+ try {
+ FileInputStream in = new FileInputStream(serverProperties);
+ Properties props = new Properties();
+ props.load(in);
+ in.close();
+
+ FileOutputStream out = new FileOutputStream(serverProperties);
+ props.setProperty("resource-pack-sha1", sha1);
+ props.store(out, null);
+ out.close();
+ } catch (Exception ex) {
+ commandSender.sendMessage("[EliteMobs] Failed to save SHA1 value " + sha1 + " ! You will have to do this manually.");
+ }
+ commandSender.sendMessage(ChatColor.GREEN + "[EliteMobs] Successfully set the value resource-pack-sha1=" + sha1 + " in server.properties!");
+ commandSender.sendMessage(ChatColor.RED + "[EliteMobs] Don't forget to update the downloadable resource pack at your online location of choice!" +
+ " If you don't update the version people download things won't work correctly!");
+ commandSender.sendMessage(ChatColor.GREEN + "[EliteMobs] The server.properties modification will work starting with the next restart!");
+
+ }
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java
new file mode 100644
index 000000000..0ac62df11
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java
@@ -0,0 +1,195 @@
+package com.magmaguy.elitemobs.config;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel;
+import com.magmaguy.elitemobs.utils.InfoMessage;
+import com.magmaguy.elitemobs.utils.SpigotMessage;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import com.magmaguy.elitemobs.utils.ZipFile;
+import org.apache.commons.io.FileUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+public class ConfigurationImporter {
+ private ConfigurationImporter() {
+ }
+
+ public static void initializeConfigs() {
+ Path configurationsPath = Paths.get(MetadataHandler.PLUGIN.getDataFolder().getAbsolutePath());
+ if (!Files.isDirectory(Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "imports"))) {
+ try {
+ Files.createDirectory(Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "imports"));
+ } catch (Exception exception) {
+ new WarningMessage("Failed to create import directory! Tell the dev!");
+ exception.printStackTrace();
+ }
+ return;
+ }
+
+ File importsFile = null;
+ try {
+ importsFile = new File(Paths.get(MetadataHandler.PLUGIN.getDataFolder().getCanonicalPath() + File.separatorChar + "imports").toString());
+ } catch (Exception ex) {
+ new WarningMessage("Failed to get imports folder! Report this to the dev!");
+ return;
+ }
+
+ if (importsFile.listFiles().length == 0)
+ return;
+ boolean importedModels = false;
+
+ for (File zippedFile : importsFile.listFiles()) {
+ File unzippedFile;
+ try {
+ if (zippedFile.getName().contains(".zip"))
+ unzippedFile = ZipFile.unzip(zippedFile.getName());
+ else unzippedFile = zippedFile;
+ } catch (Exception e) {
+ new WarningMessage("Failed to unzip config file " + zippedFile.getName() + " ! Tell the dev!");
+ e.printStackTrace();
+ continue;
+ }
+ try {
+ for (File file : unzippedFile.listFiles()) {
+ switch (file.getName()) {
+ case "custombosses":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "custombosses"));
+ break;
+ case "customitems":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "customitems"));
+ break;
+ case "customtreasurechests":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "customtreasurechests"));
+ break;
+ case "dungeonpackages":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "dungeonpackages"));
+ break;
+ case "customevents":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "customevents"));
+ break;
+ case "customspawns":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "customspawns"));
+ break;
+ case "customquests":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "customquests"));
+ break;
+ case "npcs":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "npcs"));
+ break;
+ case "wormholes":
+ moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "wormholes"));
+ break;
+ case "worldcontainer":
+ moveWorlds(file);
+ break;
+ case "ModelEngine":
+ if (Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) {
+ moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() + File.separatorChar + "ModelEngine" + File.separatorChar + "blueprints"));
+ importedModels = true;
+ } else new WarningMessage("You need ModelEngine to install custom models!");
+ break;
+ case "schematics":
+ if (Bukkit.getPluginManager().isPluginEnabled("FastAsyncWorldEdit")) {
+ moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() + File.separatorChar + "FastAsyncWorldEdit" + File.separatorChar + "schematics"));
+ } else if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) {
+ moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() + File.separatorChar + "WorldEdit" + File.separatorChar + "schematics"));
+ } else
+ new WarningMessage("You need WorldGuard or FastAsyncWorldEdit to install schematic-based minidungeons!");
+ break;
+ default:
+ new WarningMessage("Directory " + file.getName() + " for zipped file " + zippedFile.getName() + " was not a recognized directory for the file import system! Was the zipped file packaged correctly?");
+ }
+ deleteDirectory(file);
+ }
+ } catch (Exception e) {
+ new WarningMessage("Failed to move files from " + zippedFile.getName() + " ! Tell the dev!");
+ e.printStackTrace();
+ continue;
+ }
+ try {
+ unzippedFile.delete();
+ zippedFile.delete();
+ } catch (Exception ex) {
+ new WarningMessage("Failed to delete zipped file " + zippedFile.getName() + "! Tell the dev!");
+ ex.printStackTrace();
+ }
+ }
+
+ if (importedModels) {
+ CustomModel.reloadModels();
+ for (Player player : Bukkit.getOnlinePlayers())
+ if (player.hasPermission("elitemobs.*"))
+ player.spigot().sendMessage(SpigotMessage.commandHoverMessage(
+ ChatColorConverter.convert("&8[EliteMobs] &fEliteMobs just detected that recently imported files had Custom Models in them! " +
+ "&2Click here to generate the EliteMobs resource pack for those models!"),
+ "Clicking will run the command /em generateresourcepack",
+ "/em generateresourcepack"));
+ }
+
+ }
+
+ private static void deleteDirectory(File file) {
+ if (file == null)
+ return;
+ if (file.isDirectory())
+ for (File iteratedFile : file.listFiles())
+ if (iteratedFile != null)
+ deleteDirectory(iteratedFile);
+ new InfoMessage("Cleaning up " + file.getPath());
+ file.delete();
+ }
+
+ private static void moveWorlds(File worldcontainerFile) {
+ for (File file : worldcontainerFile.listFiles())
+ try {
+ File destinationFile = new File(Paths.get(Bukkit.getWorldContainer().getCanonicalPath() + File.separatorChar + file.getName()).normalize().toString());
+ if (destinationFile.exists()) {
+ new InfoMessage("Overriding existing directory " + destinationFile.getPath());
+ if (Bukkit.getWorld(file.getName()) != null) {
+ Bukkit.unloadWorld(file.getName(), false);
+ new WarningMessage("Unloaded world " + file.getName() + " for safe replacement!");
+ }
+ deleteDirectory(destinationFile);
+ }
+ FileUtils.moveDirectory(file, destinationFile);
+ } catch (Exception exception) {
+ new WarningMessage("Failed to move worlds for " + file.getName() + "! Tell the dev!");
+ exception.printStackTrace();
+ }
+ }
+
+ private static void moveDirectory(File unzippedDirectory, Path targetPath) {
+ for (File file : unzippedDirectory.listFiles())
+ try {
+ new InfoMessage("Adding " + file.getCanonicalPath());
+ moveFile(file, targetPath);
+ } catch (Exception exception) {
+ new WarningMessage("Failed to move directories for " + file.getName() + "! Tell the dev!");
+ exception.printStackTrace();
+ }
+ }
+
+ private static void moveFile(File file, Path targetPath) {
+ try {
+ if (file.isDirectory()) {
+ if (Paths.get(targetPath + "" + File.separatorChar + file.getName()).toFile().exists())
+ for (File iteratedFile : file.listFiles())
+ moveFile(iteratedFile, Paths.get(targetPath + "" + File.separatorChar + file.getName()));
+ else
+ Files.move(file.toPath(), Paths.get(targetPath + "" + File.separatorChar + file.getName()), StandardCopyOption.REPLACE_EXISTING);
+ } else
+ Files.move(file.toPath(), Paths.get(targetPath + "" + File.separatorChar + file.getName()), StandardCopyOption.REPLACE_EXISTING);
+ } catch (Exception exception) {
+ new WarningMessage("Failed to move directories for " + file.getName() + "! Tell the dev!");
+ exception.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/CustomConfig.java b/src/main/java/com/magmaguy/elitemobs/config/CustomConfig.java
new file mode 100644
index 000000000..2ead0ea97
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/CustomConfig.java
@@ -0,0 +1,175 @@
+package com.magmaguy.elitemobs.config;
+
+import com.magmaguy.elitemobs.MetadataHandler;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.reflections.Reflections;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class CustomConfig {
+
+ //This stores configurations long term, ? is the specific extended custom config field
+ private final HashMap customConfigFieldsHashMap = new HashMap<>();
+ //This is only used for loading configurations in to check if the machine has all of the default files
+ private final List customConfigFieldsArrayList = new ArrayList<>();
+ private final String folderName;
+ private final Class extends CustomConfigFields> customConfigFields;
+
+ /**
+ * Initializes all configurations and stores them in a list for later access
+ */
+ public CustomConfig(String folderName, String packageName, Class extends CustomConfigFields> customConfigFields) {
+ this.folderName = folderName;
+ this.customConfigFields = customConfigFields;
+
+ //Set defaults through reflections by getting everything that extends specific CustomConfigFields within specific package scopes
+ Reflections reflections = new Reflections(packageName);
+
+ Set classSet = new HashSet<>(reflections.getSubTypesOf(customConfigFields));
+ classSet.forEach(aClass -> {
+ try {
+ customConfigFieldsArrayList.add(aClass.newInstance());
+ } catch (Exception ex) {
+ new WarningMessage("Failed to generate plugin default classes for " + folderName + " ! This is very bad, warn the developer!");
+ ex.printStackTrace();
+ }
+ });
+
+ //Check if the directory doesn't exist
+ try {
+ if (!Files.isDirectory(Paths.get(MetadataHandler.PLUGIN.getDataFolder().getPath() + File.separatorChar + folderName))) {
+ generateFreshConfigurations();
+ return;
+ }
+ } catch (Exception ex) {
+ new WarningMessage("Failed to generate plugin default files for " + folderName + " ! This is very bad, warn the developer!");
+ ex.printStackTrace();
+ return;
+ }
+
+ //Runs if the directory exists
+ //Check if all the defaults exist
+ directoryCrawler(MetadataHandler.PLUGIN.getDataFolder().getPath() + File.separatorChar + folderName);
+
+ try {
+ //Generate missing default config files, might've been deleted or might have been added in newer version
+ if (!customConfigFieldsArrayList.isEmpty())
+ generateFreshConfigurations();
+ } catch (Exception ex) {
+ new WarningMessage("Failed to finish generating default plugin files for " + folderName + " ! This is very bad, warn the developer!");
+ ex.printStackTrace();
+ return;
+ }
+
+ }
+
+ private void directoryCrawler(String path) {
+ for (File file : Objects.requireNonNull((new File(path)).listFiles())) {
+ if (file.isFile())
+ fileInitializer(file);
+ else if (file.isDirectory())
+ directoryCrawler(file.getPath());
+ }
+ }
+
+ private void fileInitializer(File file) {
+
+ boolean isPremade = false;
+ for (Object object : customConfigFieldsArrayList) {
+ try {
+ Method getFilename = CustomConfigFields.class.getDeclaredMethod("getFilename");
+ if (file.getName().equalsIgnoreCase((String) getFilename.invoke(object))) {
+ customConfigFieldsArrayList.remove(object);
+ initialize((CustomConfigFields) object);
+ isPremade = true;
+ break;
+ }
+ } catch (Exception ex) {
+ new WarningMessage("Failed to read plugin files for " + folderName + " ! This is very bad, warn the developer!");
+ isPremade = true;
+ ex.printStackTrace();
+ }
+ }
+ if (!isPremade)
+ initialize(file);
+
+ }
+
+ public HashMap getCustomConfigFieldsHashMap() {
+ return customConfigFieldsHashMap;
+ }
+
+ /**
+ * Adds entry to custom config fields. This is done directly by the custom config fields as they are iterated through.
+ *
+ * @param filename Name of the file , using the format filename.yml
+ * @param customConfigFields Custom Config Fields, should be from an extended subclass
+ */
+ public void addCustomConfigFields(String filename, CustomConfigFields customConfigFields) {
+ customConfigFieldsHashMap.put(filename, customConfigFields);
+ }
+
+ /**
+ * Called when the appropriate configurations directory does not exist
+ */
+ private void generateFreshConfigurations() {
+ for (Object customConfigFields : customConfigFieldsArrayList)
+ initialize((CustomConfigFields) customConfigFields);
+ }
+
+ /**
+ * Initializes a single instance of a premade configuration using the default values. Writes defaults.
+ */
+ private void initialize(CustomConfigFields customConfigFields) {
+ //Create configuration file from defaults if it does not exist
+ File file = ConfigurationEngine.fileCreator(folderName, customConfigFields.getFilename());
+ //Get config file
+ FileConfiguration fileConfiguration = ConfigurationEngine.fileConfigurationCreator(file);
+
+ //Associate config
+ customConfigFields.setFile(file);
+ customConfigFields.setFileConfiguration(fileConfiguration);
+
+ //Parse actual fields and load into RAM to be used
+ customConfigFields.processConfigFields();
+
+ //Save all configuration values as they exist
+ ConfigurationEngine.fileSaverCustomValues(fileConfiguration, file);
+
+ //if (customConfigFields.isEnabled)
+ //Store for use by the plugin
+ addCustomConfigFields(file.getName(), customConfigFields);
+ }
+
+ /**
+ * Called when a user-made file is detected.
+ */
+ private void initialize(File file) {
+ //Load file configuration from file
+ try {
+ FileConfiguration fileConfiguration = YamlConfiguration.loadConfiguration(file);
+ //Instantiate the correct CustomConfigFields instance
+ Constructor> constructor = customConfigFields.getConstructor(String.class, boolean.class);
+ CustomConfigFields instancedCustomConfigFields = (CustomConfigFields) constructor.newInstance(file.getName(), true);
+ instancedCustomConfigFields.setFileConfiguration(fileConfiguration);
+ instancedCustomConfigFields.setFile(file);
+ //Parse actual fields and load into RAM to be used
+ instancedCustomConfigFields.processConfigFields();
+ //if (instancedCustomConfigFields.isEnabled)
+ //Store for use by the plugin
+ addCustomConfigFields(file.getName(), instancedCustomConfigFields);
+ } catch (Exception ex) {
+ new WarningMessage("Bad constructor for file " + file.getName());
+ ex.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/magmaguy/elitemobs/config/CustomConfigConstructor.java b/src/main/java/com/magmaguy/elitemobs/config/CustomConfigConstructor.java
deleted file mode 100644
index 10f18ba99..000000000
--- a/src/main/java/com/magmaguy/elitemobs/config/CustomConfigConstructor.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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 com.magmaguy.elitemobs.config;
-
-/**
- * Created by MagmaGuy on 01/05/2017.
- */
-
-import com.magmaguy.elitemobs.MetadataHandler;
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.InvalidConfigurationException;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.plugin.Plugin;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-public class CustomConfigConstructor extends YamlConfiguration {
-
- Plugin plugin = Bukkit.getPluginManager().getPlugin(MetadataHandler.ELITE_MOBS);
- private File file;
- private String defaults;
-
- /**
- * Creates new PluginFile, without defaults
- *
- * @param fileName - Name of the file
- */
- public CustomConfigConstructor(String fileName) {
- this(fileName, null);
- }
-
- /**
- * Creates new PluginFile, with defaults
- *
- * @param fileName - Name of the file
- * @param defaultsName - Name of the defaults
- */
- public CustomConfigConstructor(String fileName, String defaultsName) {
- this.defaults = defaultsName;
- File newFile = new File(plugin.getDataFolder().getPath()+"/data");
- Bukkit.getLogger().info("ATTENTION: " + newFile.toString());
- this.file = new File(newFile, fileName);
- reload();
- }
-
- /**
- * Reload configuration
- */
- public void reload() {
-
- if (!file.exists()) {
-
- try {
- file.getParentFile().mkdirs();
- file.createNewFile();
-
- } catch (IOException exception) {
- exception.printStackTrace();
- plugin.getLogger().severe("Error while creating file " + file.getName());
- }
-
- }
-
- try {
- load(file);
-
- if (defaults != null) {
- InputStreamReader reader = new InputStreamReader(plugin.getResource(defaults));
- FileConfiguration defaultsConfig = YamlConfiguration.loadConfiguration(reader);
-
- setDefaults(defaultsConfig);
- options().copyDefaults(true);
-
- reader.close();
- save();
- }
-
- } catch (IOException exception) {
- exception.printStackTrace();
- plugin.getLogger().severe("Error while loading file " + file.getName());
-
- } catch (InvalidConfigurationException exception) {
- exception.printStackTrace();
- plugin.getLogger().severe("Error while loading file " + file.getName());
-
- }
-
- }
-
- /**
- * Save configuration
- */
- public void save() {
-
- try {
- options().indent(2);
- save(file);
-
- } catch (IOException exception) {
- exception.printStackTrace();
- plugin.getLogger().severe("Error while saving file " + file.getName());
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/src/main/java/com/magmaguy/elitemobs/config/CustomConfigFields.java b/src/main/java/com/magmaguy/elitemobs/config/CustomConfigFields.java
new file mode 100644
index 000000000..1989dcbbe
--- /dev/null
+++ b/src/main/java/com/magmaguy/elitemobs/config/CustomConfigFields.java
@@ -0,0 +1,354 @@
+package com.magmaguy.elitemobs.config;
+
+import com.magmaguy.elitemobs.ChatColorConverter;
+import com.magmaguy.elitemobs.utils.ConfigurationLocation;
+import com.magmaguy.elitemobs.utils.ItemStackGenerator;
+import com.magmaguy.elitemobs.utils.WarningMessage;
+import org.bukkit.*;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.LeatherArmorMeta;
+import org.bukkit.inventory.meta.SkullMeta;
+import org.bukkit.util.Vector;
+
+import java.io.File;
+import java.util.*;
+
+public class CustomConfigFields implements CustomConfigFieldsInterface {
+
+ protected String filename;
+ protected boolean isEnabled;
+ protected FileConfiguration fileConfiguration;
+ protected File file;
+
+ /**
+ * Used by plugin-generated files (defaults)
+ *
+ * @param filename
+ * @param isEnabled
+ */
+ public CustomConfigFields(String filename, boolean isEnabled) {
+ this.filename = filename.contains(".yml") ? filename : filename + ".yml";
+ this.isEnabled = isEnabled;
+ }
+
+ public String getFilename() {
+ return filename;
+ }
+
+ public boolean isEnabled() {
+ return isEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ isEnabled = enabled;
+ }
+
+ public FileConfiguration getFileConfiguration() {
+ return fileConfiguration;
+ }
+
+ public void setFileConfiguration(FileConfiguration fileConfiguration) {
+ this.fileConfiguration = fileConfiguration;
+ }
+
+ public File getFile() {
+ return file;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ @Override
+ public void processConfigFields() {
+
+ }
+
+ protected boolean configHas(String configKey) {
+ return fileConfiguration.contains(configKey);
+ }
+
+ protected String processString(String path, String value, String pluginDefault, boolean forceWriteDefault) {
+ if (!configHas(path)) {
+ if (forceWriteDefault || !Objects.equals(value, pluginDefault))
+ fileConfiguration.addDefault(path, value);
+ return value;
+ }
+ try {
+ return ChatColorConverter.convert(fileConfiguration.getString(path));
+ } catch (Exception ex) {
+ new WarningMessage("File " + filename + " has an incorrect entry for " + path);
+ new WarningMessage("Entry: " + value);
+ }
+ return value;
+ }
+
+ public List processStringList(String path, List value, List pluginDefault, boolean forceWriteDefault) {
+ if (!configHas(path)) {
+ if (forceWriteDefault || value != pluginDefault)
+ fileConfiguration.addDefault(path, value);
+ return value;
+ }
+ try {
+ List list = new ArrayList<>();
+ for (String string : fileConfiguration.getStringList(path))
+ list.add(ChatColorConverter.convert(string));
+ return list;
+ } catch (Exception ex) {
+ new WarningMessage("File " + filename + " has an incorrect entry for " + path);
+ new WarningMessage("Entry: " + value);
+ }
+ return value;
+ }
+
+ /**
+ * This not only gets a list of worlds, but gets a list of already loaded worlds. This might cause issues if the worlds
+ * aren't loaded when the code for getting worlds runs.
+ *
+ * @param path Configuration path
+ * @param pluginDefault Default value - should be null or empty
+ * @return Worlds from the list that are loaded at the time this runs, probably on startup
+ */
+ protected List processWorldList(String path, List value, List pluginDefault, boolean forceWriteDefault) {
+ if (!configHas(path)) {
+ if (value != null && (forceWriteDefault || value != pluginDefault))
+ processStringList(path, worldListToStringListConverter(value), worldListToStringListConverter(pluginDefault), forceWriteDefault);
+ return value;
+ }
+ try {
+ List validWorldStrings = processStringList(path, worldListToStringListConverter(pluginDefault), worldListToStringListConverter(value), forceWriteDefault);
+ List validWorlds = new ArrayList<>();
+ if (!validWorldStrings.isEmpty())
+ for (String string : validWorldStrings) {
+ World world = Bukkit.getWorld(string);
+ if (world != null)
+ validWorlds.add(world);
+ }
+ return validWorlds;
+ } catch (Exception ex) {
+ new WarningMessage("File " + filename + " has an incorrect entry for " + path);
+ new WarningMessage("Entry: " + value);
+ }
+ return value;
+ }
+
+ private List