diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..e1f4a52 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,19 @@ +*The following template is required if you report a bug. For a suggestion, you can clear this, but don't forget to open one issue per suggestion!* + +#### Environment + +* **Minecraft version**: +* **Plateform used**: CraftBukkit / Spigot +* **Bukkit or Spigot version**: +* **Plugin version**: +* **Plugin build number**: (Check out the CONTRIBUTING file linked above the form to see where this number is) + + +#### Problem description + +Write here a description of the problem you encounter. Remember to also use a descriptive title for your issue! + + +#### Steps to reproduce + +Write here how we can reproduce this bug, if applicable. This help us to understand the problem and fix it quicker. diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a771d59..0000000 --- a/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: java -jdk: - - oraclejdk7 - - openjdk7 - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d31c0c..8500775 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,4 +20,5 @@ ### Suggestions -1. Please check if the feature is not already implemented in the [latest development build](http://jenkins.carrade.eu/job/UltraHardcoreReloaded/), or [planned in the future](https://github.com/AmauryCarrade/UHPlugin/labels/enhancement). \ No newline at end of file +1. Please **check if the feature is not already implemented** in the [latest development build](http://jenkins.carrade.eu/job/UltraHardcoreReloaded/), **or [planned in the future](https://github.com/AmauryCarrade/UHPlugin/labels/enhancement)**. +2. Open **one issue per suggestion**, not one issue with multiple ideas. diff --git a/LICENSE b/LICENSE index 4b9f60d..2b8cfbb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,622 +1,518 @@ +CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL-B - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] - 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 + + Avertissement + +Ce contrat est une licence de logiciel libre issue d'une concertation +entre ses auteurs afin que le respect de deux grands principes préside à +sa rédaction: + + * d'une part, le respect des principes de diffusion des logiciels + libres: accès au code source, droits étendus conférés aux + utilisateurs, + * d'autre part, la désignation d'un droit applicable, le droit + français, auquel elle est conforme, tant au regard du droit de la + responsabilité civile que du droit de la propriété intellectuelle + et de la protection qu'il offre aux auteurs et titulaires des + droits patrimoniaux sur un logiciel. + +Les auteurs de la licence CeCILL-B (pour Ce[a] C[nrs] I[nria] L[ogiciel] +L[ibre]) sont: + +Commissariat à l'Energie Atomique - CEA, établissement public de +recherche à caractère scientifique, technique et industriel, dont le +siège est situé 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris. + +Centre National de la Recherche Scientifique - CNRS, établissement +public à caractère scientifique et technologique, dont le siège est +situé 3 rue Michel-Ange, 75794 Paris cedex 16. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, établissement public à caractère scientifique et technologique, +dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153 +Le Chesnay cedex. + + + Préambule + +Ce contrat est une licence de logiciel libre dont l'objectif est de +conférer aux utilisateurs une très large liberté de modification et de +redistribution du logiciel régi par cette licence. + +L'exercice de cette liberté est assorti d'une obligation forte de +citation à la charge de ceux qui distribueraient un logiciel incorporant +un logiciel régi par la présente licence afin d'assurer que les +contributions de tous soient correctement identifiées et reconnues. + +L'accessibilité au code source et les droits de copie, de modification +et de redistribution qui découlent de ce contrat ont pour contrepartie +de n'offrir aux utilisateurs qu'une garantie limitée et de ne faire +peser sur l'auteur du logiciel, le titulaire des droits patrimoniaux et +les concédants successifs qu'une responsabilité restreinte. + +A cet égard l'attention de l'utilisateur est attirée sur les risques +associés au chargement, à l'utilisation, à la modification et/ou au +développement et à la reproduction du logiciel par l'utilisateur étant +donné sa spécificité de logiciel libre, qui peut le rendre complexe à +manipuler et qui le réserve donc à des développeurs ou des +professionnels avertis possédant des connaissances informatiques +approfondies. Les utilisateurs sont donc invités à charger et tester +l'adéquation du logiciel à leurs besoins dans des conditions permettant +d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus +généralement, à l'utiliser et l'exploiter dans les mêmes conditions de +sécurité. Ce contrat peut être reproduit et diffusé librement, sous +réserve de le conserver en l'état, sans ajout ni suppression de clauses. + +Ce contrat est susceptible de s'appliquer à tout logiciel dont le +titulaire des droits patrimoniaux décide de soumettre l'exploitation aux +dispositions qu'il contient. + + + Article 1 - DEFINITIONS + +Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une +lettre capitale, auront la signification suivante: + +Contrat: désigne le présent contrat de licence, ses éventuelles versions +postérieures et annexes. + +Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code +Source et le cas échéant sa documentation, dans leur état au moment de +l'acceptation du Contrat par le Licencié. + +Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et +éventuellement de Code Objet et le cas échéant sa documentation, dans +leur état au moment de leur première diffusion sous les termes du Contrat. + +Logiciel Modifié: désigne le Logiciel modifié par au moins une +Contribution. + +Code Source: désigne l'ensemble des instructions et des lignes de +programme du Logiciel et auquel l'accès est nécessaire en vue de +modifier le Logiciel. + +Code Objet: désigne les fichiers binaires issus de la compilation du +Code Source. + +Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur +sur le Logiciel Initial. + +Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le +Contrat. + +Contributeur: désigne le Licencié auteur d'au moins une Contribution. + +Concédant: désigne le Titulaire ou toute personne physique ou morale +distribuant le Logiciel sous le Contrat. + +Contribution: désigne l'ensemble des modifications, corrections, +traductions, adaptations et/ou nouvelles fonctionnalités intégrées dans +le Logiciel par tout Contributeur, ainsi que tout Module Interne. + +Module: désigne un ensemble de fichiers sources y compris leur +documentation qui permet de réaliser des fonctionnalités ou services +supplémentaires à ceux fournis par le Logiciel. + +Module Externe: désigne tout Module, non dérivé du Logiciel, tel que ce +Module et le Logiciel s'exécutent dans des espaces d'adressage +différents, l'un appelant l'autre au moment de leur exécution. + +Module Interne: désigne tout Module lié au Logiciel de telle sorte +qu'ils s'exécutent dans le même espace d'adressage. + +Parties: désigne collectivement le Licencié et le Concédant. + +Ces termes s'entendent au singulier comme au pluriel. + + + Article 2 - OBJET + +Le Contrat a pour objet la concession par le Concédant au Licencié d'une +licence non exclusive, cessible et mondiale du Logiciel telle que +définie ci-après à l'article 5 pour toute la durée de protection des droits +portant sur ce Logiciel. + + + Article 3 - ACCEPTATION + +3.1 L'acceptation par le Licencié des termes du Contrat est réputée +acquise du fait du premier des faits suivants: + + * (i) le chargement du Logiciel par tout moyen notamment par + téléchargement à partir d'un serveur distant ou par chargement à + partir d'un support physique; + * (ii) le premier exercice par le Licencié de l'un quelconque des + droits concédés par le Contrat. + +3.2 Un exemplaire du Contrat, contenant notamment un avertissement +relatif aux spécificités du Logiciel, à la restriction de garantie et à +la limitation à un usage par des utilisateurs expérimentés a été mis à +disposition du Licencié préalablement à son acceptation telle que +définie à l'article 3.1 ci dessus et le Licencié reconnaît en avoir pris +connaissance. + + + Article 4 - ENTREE EN VIGUEUR ET DUREE + + + 4.1 ENTREE EN VIGUEUR + +Le Contrat entre en vigueur à la date de son acceptation par le Licencié +telle que définie en 3.1. + + + 4.2 DUREE + +Le Contrat produira ses effets pendant toute la durée légale de +protection des droits patrimoniaux portant sur le Logiciel. + + + Article 5 - ETENDUE DES DROITS CONCEDES + +Le Concédant concède au Licencié, qui accepte, les droits suivants sur +le Logiciel pour toutes destinations et pour la durée du Contrat dans +les conditions ci-après détaillées. + +Par ailleurs, si le Concédant détient ou venait à détenir un ou +plusieurs brevets d'invention protégeant tout ou partie des +fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas +opposer les éventuels droits conférés par ces brevets aux Licenciés +successifs qui utiliseraient, exploiteraient ou modifieraient le +Logiciel. En cas de cession de ces brevets, le Concédant s'engage à +faire reprendre les obligations du présent alinéa aux cessionnaires. + + + 5.1 DROIT D'UTILISATION + +Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant +aux domaines d'application, étant ci-après précisé que cela comporte: + + 1. la reproduction permanente ou provisoire du Logiciel en tout ou + partie par tout moyen et sous toute forme. + + 2. le chargement, l'affichage, l'exécution, ou le stockage du + Logiciel sur tout support. + + 3. la possibilité d'en observer, d'en étudier, ou d'en tester le + fonctionnement afin de déterminer les idées et principes qui sont + à la base de n'importe quel élément de ce Logiciel; et ceci, + lorsque le Licencié effectue toute opération de chargement, + d'affichage, d'exécution, de transmission ou de stockage du + Logiciel qu'il est en droit d'effectuer en vertu du Contrat. + + + 5.2 DROIT D'APPORTER DES CONTRIBUTIONS + +Le droit d'apporter des Contributions comporte le droit de traduire, +d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel +et le droit de reproduire le logiciel en résultant. + +Le Licencié est autorisé à apporter toute Contribution au Logiciel sous +réserve de mentionner, de façon explicite, son nom en tant qu'auteur de +cette Contribution et la date de création de celle-ci. + + + 5.3 DROIT DE DISTRIBUTION + +Le droit de distribution comporte notamment le droit de diffuser, de +transmettre et de communiquer le Logiciel au public sur tout support et +par tout moyen ainsi que le droit de mettre sur le marché à titre +onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé. + +Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou +non, à des tiers dans les conditions ci-après détaillées. + + + 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION + +Le Licencié est autorisé à distribuer des copies conformes du Logiciel, +sous forme de Code Source ou de Code Objet, à condition que cette +distribution respecte les dispositions du Contrat dans leur totalité et +soit accompagnée: + + 1. d'un exemplaire du Contrat, + + 2. d'un avertissement relatif à la restriction de garantie et de + responsabilité du Concédant telle que prévue aux articles 8 + et 9, + +et que, dans le cas où seul le Code Objet du Logiciel est redistribué, +le Licencié permette un accès effectif au Code Source complet du +Logiciel pendant au moins toute la durée de sa distribution du Logiciel, +étant entendu que le coût additionnel d'acquisition du Code Source ne +devra pas excéder le simple coût de transfert des données. + + + 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE + +Lorsque le Licencié apporte une Contribution au Logiciel, le Logiciel +Modifié peut être distribué sous un contrat de licence autre que le +présent Contrat sous réserve du respect des dispositions de l'article +5.3.4. + + + 5.3.3 DISTRIBUTION DES MODULES EXTERNES + +Lorsque le Licencié a développé un Module Externe les conditions du +Contrat ne s'appliquent pas à ce Module Externe, qui peut être distribué +sous un contrat de licence différent. + + + 5.3.4 CITATIONS + +Le Licencié qui distribue un Logiciel Modifié s'engage expressément: + + 1. à indiquer dans sa documentation qu'il a été réalisé à partir du + Logiciel régi par le Contrat, en reproduisant les mentions de + propriété intellectuelle du Logiciel, + + 2. à faire en sorte que l'utilisation du Logiciel, ses mentions de + propriété intellectuelle et le fait qu'il est régi par le Contrat + soient indiqués dans un texte facilement accessible depuis + l'interface du Logiciel Modifié, + + 3. à mentionner, sur un site Web librement accessible décrivant le + Logiciel Modifié, et pendant au moins toute la durée de sa + distribution, qu'il a été réalisé à partir du Logiciel régi par le + Contrat, en reproduisant les mentions de propriété intellectuelle + du Logiciel, + + 4. lorsqu'il le distribue à un tiers susceptible de distribuer + lui-même un Logiciel Modifié, sans avoir à en distribuer le code + source, à faire ses meilleurs efforts pour que les obligations du + présent article 5.3.4 soient reprises par le dit tiers. + +Lorsque le Logiciel modifié ou non est distribué avec un Module Externe +qui a été conçu pour l'utiliser, le Licencié doit soumettre le dit +Module Externe aux obligations précédentes. + + + 5.3.5 COMPATIBILITE AVEC LES LICENCES CeCILL et CeCILL-C + +Lorsqu'un Logiciel Modifié contient une Contribution soumise au contrat +de licence CeCILL, les stipulations prévues à l'article 5.3.4 sont +facultatives. + +Un Logiciel Modifié peut être distribué sous le contrat de licence +CeCILL-C. Les stipulations prévues à l'article 5.3.4 sont alors +facultatives. + + + Article 6 - PROPRIETE INTELLECTUELLE + + + 6.1 SUR LE LOGICIEL INITIAL + +Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel +Initial. Toute utilisation du Logiciel Initial est soumise au respect +des conditions dans lesquelles le Titulaire a choisi de diffuser son +oeuvre et nul autre n'a la faculté de modifier les conditions de +diffusion de ce Logiciel Initial. + +Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi +par le Contrat et ce, pour la durée visée à l'article 4.2. + + + 6.2 SUR LES CONTRIBUTIONS + +Le Licencié qui a développé une Contribution est titulaire sur celle-ci +des droits de propriété intellectuelle dans les conditions définies par +la législation applicable. + + + 6.3 SUR LES MODULES EXTERNES + +Le Licencié qui a développé un Module Externe est titulaire sur celui-ci +des droits de propriété intellectuelle dans les conditions définies par +la législation applicable et reste libre du choix du contrat régissant +sa diffusion. + + + 6.4 DISPOSITIONS COMMUNES + +Le Licencié s'engage expressément: + + 1. à ne pas supprimer ou modifier de quelque manière que ce soit les + mentions de propriété intellectuelle apposées sur le Logiciel; + + 2. à reproduire à l'identique lesdites mentions de propriété + intellectuelle sur les copies du Logiciel modifié ou non. + +Le Licencié s'engage à ne pas porter atteinte, directement ou +indirectement, aux droits de propriété intellectuelle du Titulaire et/ou +des Contributeurs sur le Logiciel et à prendre, le cas échéant, à +l'égard de son personnel toutes les mesures nécessaires pour assurer le +respect des dits droits de propriété intellectuelle du Titulaire et/ou +des Contributeurs. + + + Article 7 - SERVICES ASSOCIES + +7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de +prestations d'assistance technique ou de maintenance du Logiciel. + +Cependant le Concédant reste libre de proposer ce type de services. Les +termes et conditions d'une telle assistance technique et/ou d'une telle +maintenance seront alors déterminés dans un acte séparé. Ces actes de +maintenance et/ou assistance technique n'engageront que la seule +responsabilité du Concédant qui les propose. + +7.2 De même, tout Concédant est libre de proposer, sous sa seule +responsabilité, à ses licenciés une garantie, qui n'engagera que lui, +lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce, +dans les conditions qu'il souhaite. Cette garantie et les modalités +financières de son application feront l'objet d'un acte séparé entre le +Concédant et le Licencié. + + + Article 8 - RESPONSABILITE + +8.1 Sous réserve des dispositions de l'article 8.2, le Licencié a la +faculté, sous réserve de prouver la faute du Concédant concerné, de +solliciter la réparation du préjudice direct qu'il subirait du fait du +Logiciel et dont il apportera la preuve. + +8.2 La responsabilité du Concédant est limitée aux engagements pris en +application du Contrat et ne saurait être engagée en raison notamment: +(i) des dommages dus à l'inexécution, totale ou partielle, de ses +obligations par le Licencié, (ii) des dommages directs ou indirects +découlant de l'utilisation ou des performances du Logiciel subis par le +Licencié et (iii) plus généralement d'un quelconque dommage indirect. En +particulier, les Parties conviennent expressément que tout préjudice +financier ou commercial (par exemple perte de données, perte de +bénéfices, perte d'exploitation, perte de clientèle ou de commandes, +manque à gagner, trouble commercial quelconque) ou toute action dirigée +contre le Licencié par un tiers, constitue un dommage indirect et +n'ouvre pas droit à réparation par le Concédant. + + + Article 9 - GARANTIE + +9.1 Le Licencié reconnaît que l'état actuel des connaissances +scientifiques et techniques au moment de la mise en circulation du +Logiciel ne permet pas d'en tester et d'en vérifier toutes les +utilisations ni de détecter l'existence d'éventuels défauts. L'attention +du Licencié a été attirée sur ce point sur les risques associés au +chargement, à l'utilisation, la modification et/ou au développement et à +la reproduction du Logiciel qui sont réservés à des utilisateurs avertis. + +Il relève de la responsabilité du Licencié de contrôler, par tous +moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et +de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens. + +9.2 Le Concédant déclare de bonne foi être en droit de concéder +l'ensemble des droits attachés au Logiciel (comprenant notamment les +droits visés à l'article 5). + +9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le +Concédant sans autre garantie, expresse ou tacite, que celle prévue à +l'article 9.2 et notamment sans aucune garantie sur sa valeur commerciale, +son caractère sécurisé, innovant ou pertinent. + +En particulier, le Concédant ne garantit pas que le Logiciel est exempt +d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible +avec l'équipement du Licencié et sa configuration logicielle ni qu'il +remplira les besoins du Licencié. + +9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le +Logiciel ne porte pas atteinte à un quelconque droit de propriété +intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout +autre droit de propriété. Ainsi, le Concédant exclut toute garantie au +profit du Licencié contre les actions en contrefaçon qui pourraient être +diligentées au titre de l'utilisation, de la modification, et de la +redistribution du Logiciel. Néanmoins, si de telles actions sont +exercées contre le Licencié, le Concédant lui apportera son aide +technique et juridique pour sa défense. Cette aide technique et +juridique est déterminée au cas par cas entre le Concédant concerné et +le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage +toute responsabilité quant à l'utilisation de la dénomination du +Logiciel par le Licencié. Aucune garantie n'est apportée quant à +l'existence de droits antérieurs sur le nom du Logiciel et sur +l'existence d'une marque. + + + Article 10 - RESILIATION + +10.1 En cas de manquement par le Licencié aux obligations mises à sa +charge par le Contrat, le Concédant pourra résilier de plein droit le +Contrat trente (30) jours après notification adressée au Licencié et +restée sans effet. + +10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à +utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les +licences qu'il aura concédées antérieurement à la résiliation du Contrat +resteront valides sous réserve qu'elles aient été effectuées en +conformité avec le Contrat. + + + Article 11 - DISPOSITIONS DIVERSES + + + 11.1 CAUSE EXTERIEURE + +Aucune des Parties ne sera responsable d'un retard ou d'une défaillance +d'exécution du Contrat qui serait dû à un cas de force majeure, un cas +fortuit ou une cause extérieure, telle que, notamment, le mauvais +fonctionnement ou les interruptions du réseau électrique ou de +télécommunication, la paralysie du réseau liée à une attaque +informatique, l'intervention des autorités gouvernementales, les +catastrophes naturelles, les dégâts des eaux, les tremblements de terre, +le feu, les explosions, les grèves et les conflits sociaux, l'état de +guerre... + +11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou +plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du +Contrat, ne pourra en aucun cas impliquer renonciation par la Partie +intéressée à s'en prévaloir ultérieurement. + +11.3 Le Contrat annule et remplace toute convention antérieure, écrite +ou orale, entre les Parties sur le même objet et constitue l'accord +entier entre les Parties sur cet objet. Aucune addition ou modification +aux termes du Contrat n'aura d'effet à l'égard des Parties à moins +d'être faite par écrit et signée par leurs représentants dûment habilités. + +11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat +s'avèrerait contraire à une loi ou à un texte applicable, existants ou +futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les +amendements nécessaires pour se conformer à cette loi ou à ce texte. +Toutes les autres dispositions resteront en vigueur. De même, la +nullité, pour quelque raison que ce soit, d'une des dispositions du +Contrat ne saurait entraîner la nullité de l'ensemble du Contrat. + + + 11.5 LANGUE + +Le Contrat est rédigé en langue française et en langue anglaise, ces +deux versions faisant également foi. + + + Article 12 - NOUVELLES VERSIONS DU CONTRAT + +12.1 Toute personne est autorisée à copier et distribuer des copies de +ce Contrat. + +12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé +et ne peut être modifié que par les auteurs de la licence, lesquels se +réservent le droit de publier périodiquement des mises à jour ou de +nouvelles versions du Contrat, qui posséderont chacune un numéro +distinct. Ces versions ultérieures seront susceptibles de prendre en +compte de nouvelles problématiques rencontrées par les logiciels libres. + +12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra +faire l'objet d'une diffusion ultérieure que sous la même version du +Contrat ou une version postérieure. + + + Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE + +13.1 Le Contrat est régi par la loi française. Les Parties conviennent +de tenter de régler à l'amiable les différends ou litiges qui +viendraient à se produire par suite ou à l'occasion du Contrat. + +13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter +de leur survenance et sauf situation relevant d'une procédure d'urgence, +les différends ou litiges seront portés par la Partie la plus diligente +devant les Tribunaux compétents de Paris. + + +Version 1.0 du 2006-09-05. diff --git a/README.md b/README.md index 88ce34d..9706dd8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# UltraHardcore, reloaded +# UltraHardcore, reloaded [![Build Status](http://jenkins.carrade.eu/job/UltraHardcoreReloaded/badge/icon)](http://jenkins.carrade.eu/job/UltraHardcoreReloaded/) + C'est très la source. @@ -7,7 +8,6 @@ Development builds available for each commit [on our Jenkins server](http://jenk This plugin is [available on BukkitDev](http://dev.bukkit.org/bukkit-plugins/uhc/). Please note, this README reflects the last development version. Some features listed here may not be in the version published on BukkitDev. -[![Build Status](https://travis-ci.org/AmauryCarrade/UHPlugin.svg?branch=master)](https://travis-ci.org/AmauryCarrade/UHPlugin) 1. [Features](#features) 1. [Teams](#manages-teams) @@ -23,11 +23,16 @@ Please note, this README reflects the last development version. Some features li 1. [Miscellaneous](#miscellaneous-features) 1. [Commands & permissions](#commands--permissions) 1. [Installation](#installation) -1. [How to translate the plugin](#how-to-translate-the-plugin-in-your-own-language) +1. [How to translate the plugin](#how-to-translate-the-plugin-or-change-strings-in-your-own-language) + 1. [If you want to translate it for yourself](#if-you-want-to-translate-it-for-yourself) + 1. [If you want to translate it for everyone](#if-you-want-to-translate-it-for-everyone) + 1. [Inside the translations](#inside-the-translations) 1. [Metrics](#metrics) 1. [Thanks](#thanks) + 1. [Translators](#translators) 1. [License](#license) + ## Features For available configuration, please [see directly the configuration file](https://github.com/AmauryCarrade/UHPlugin/blob/master/src/main/resources/config.yml). @@ -267,29 +272,34 @@ After the installation, I recommend you to: 5. only after that, generate the wall (`/uh generatewalls`) (don't forget to configure the shape and the size in the config file before). Otherwise, holes will be formed in the wall when Minecraft will populate the terrain. -## How to translate the plugin in your own language +## How to translate the plugin (or change strings) in your own language -It's pretty simple. +### If you want to translate it for yourself -1. **Duplicate a language file** in the `plugins/UHPlugin/i18n/` folder of your server. - Name the file `language_COUNTRY.yml` (like the other ones). -2. Open the new language file with a text editor (like notepad, gedit, kate, vi, etc.) and **translate the strings**. - *DON'T change the keys*, only the strings after the comas. - Also, *never use tabulations in these files*, *don't change the indentation* and *don't remove the quotes around the sentences*. -3. When the translation is done, open the `manifest.yml` file (in the same folder) and **add the name of the new language file** (without the `.yml`) in the list: - - ```yml - version: 1.0 - languages: - - en_US - - fr_FR - - # ... - - language_COUNTRY - ``` -4. In the `config.yml`, **change the `lang` key** to the name of the new language. That's all! +1. Go to the `plugins/UHPlugin/i18n` folder in your server directory. You have to start the server with this plugin at least one time before. +2. Locate your language file. The name is `language_COUNTRY.po`. +3. Open it, either using a simple text editor, or, if you like GUIs, with POEdit, a translation files editor. +4. Add or update translations, save the file, reload the server. + +If you update the plugin to a new version, the translation files will be replaced by the new ones, but a backup of your changes will be automatically made in the `plugins/UHPlugin/i18n/backups//` folder. + + +### If you want to translate it for everyone -Also, send me the translation, so I can integrate it inside the plugin! +We use [Transifex](https://www.transifex.com/zdevelopers/uhcreloaded/dashboard/) to translate the plugin. +1. Go to [the Transifex project page of this plugin](https://www.transifex.com/zdevelopers/uhcreloaded/dashboard/). Create an account if you don't have one. +2. Click « **Join team** » on the top left of the page. +3. Select your langage in the list. + - If your language is not listed, request it by clicking on [`... » Request language`](http://raw.carrade.eu/s/1453385835.png). +4. Translate. + +When translated, we update the translations in the plugin as soon as possible. + +You can also open a Pull-Request with a new or updated `po` file, if you want. + + +### Inside the translations While translating, you will see some special keys, like `{0}` or `{blue}`. These values are replaced by the plugin; see below. @@ -333,9 +343,26 @@ To opt out of metrics you can edit the `config.yml` file in the `PluginMetrics` ## Thanks - This work is a fork of [the KTP plugin](https://github.com/Azenet/KTP) made by [@Azenet](https://github.com/Azenet). - - Special thanks to [@jonyroda97](https://github.com/jonyroda97), for many interesting suggestions and Portuguese translation. + *The original project was published under GPLv3, but without any piece of code in common between this original and the current project, the license was changed to CeCILL-B.* + - Special thanks to [@jonyroda97](https://github.com/jonyroda97) and [@Amauryroco](https://github.com/Amauryroco), for many interesting suggestions. + + +### Translators + + - **English** *(original)* + - [Amaury Carrade](https://github.com/AmauryCarrade) + - **French** + - [Amaury Carrade](https://github.com/AmauryCarrade) + - **Portuguese (Portugal)** + - [João Roda](https://github.com/jonyroda97) + - **Portuguese (Brazil)** + - [eraizel](https://github.com/eraizel) + - **Czech** + - [Nojp (Amunak)](https://github.com/Amunak) + - **Simplified Chinese** + - [h404bi](https://github.com/h404bi) ## License -GPLv3. Voir le fichier LICENSE pour détails. +This software is published under the **CeCILL-B** license. See the `LICENSE` file for details. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 46e6d12..432cc3b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,155 +1,233 @@ - - 4.0.0 - me.azenet - UHPlugin - 1.3-SNAPSHOT - UHPlugin - Ultra Hardcore plugin - https://github.com/AmauryCarrade/UHPlugin/ - - GitHub - https://github.com/AmauryCarrade/UHPlugin/issues - - - - scm:git:https://github.com/AmauryCarrade/UHPlugin.git - https://github.com/AmauryCarrade/UHPlugin.git - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.codehaus.mojo - buildnumber-maven-plugin - 1.3 - - - validate - - create - - - - - false - false - 10 - - - - org.apache.maven.plugins - maven-jar-plugin - 2.1 - - - - ${buildNumber} - ${scmBranch} - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.3 - - - - org.mcstats.*:* - - - - - org.mcstats - me.azenet.UHPlugin - - - - - - package - - shade - - - - - - - - - spigot-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - - dynmap-repo - http://repo.mikeprimm.com/ - - - shadowvolt-repo - Shadowvolt Repository - http://ci.shadowvolt.com/plugin/repository/everything/ - - - - comphenix-mirror-repo - Mirror of the comphenix repository - http://minor.royaldev.org:8081/nexus/content/groups/public/ - - - carrade-repo - http://depot.carrade.eu/maven2/ - - - Plugin Metrics - http://repo.mcstats.org/content/repositories/public - - - - - org.bukkit - bukkit - 1.8-R0.1-SNAPSHOT - jar - provided - - - com.wimbli.WorldBorder - WorldBorder - 1.8.0 - provided - - - com.pgcraft - SpectatorPlus - 1.9.2 - provided - - - org.dynmap - dynmap-api - 1.8 - - - com.comphenix.protocol - ProtocolLib - 3.6.3-SNAPSHOT - - - org.mcstats.bukkit - metrics-lite - R7 - compile - - + + + 4.0.0 + eu.carrade.amaury + UHCReloaded + 1.4 + UHCReloaded + Ultra Hardcore plugin + https://github.com/zDevelopers/UHPlugin/ + + + GitHub + https://github.com/zDevelopers/UHPlugin/issues + + + + scm:git:https://github.com/zDevelopers/UHPlugin.git + https://github.com/zDevelopers/UHPlugin.git + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.3 + + + validate + + create + + + + + false + false + 10 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.1 + + + + ${buildNumber} + ${scmBranch} + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + true + + + org.mcstats.*:* + fr.zcraft:zlib + + + + + org.mcstats + eu.carrade.amaury.UHCReloaded.mcstats + + + fr.zcraft.zlib + eu.carrade.amaury.UHCReloaded.zlib + + + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + -XX:-UseSplitVerifier -noverify + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + dynmap-repo + http://repo.mikeprimm.com/ + + + dmulloy2-repo + Dmulloy2 Repository (ProtocolLib) + http://repo.dmulloy2.net/content/groups/public/ + + + pgmann-repo + PGMann repository (SpectatorPlus) + https://mvn.pgmann.cf/ + + + carrade-repo + http://depot.carrade.eu/maven2/ + + + zDevelopers + http://maven.carrade.eu/artifactory/snapshots + + + Plugin Metrics + http://repo.mcstats.org/content/repositories/public + + + + + org.bukkit + bukkit + 1.8.3-R0.1-SNAPSHOT + jar + + + fr.zcraft + zlib + 0.99-SNAPSHOT + + + com.wimbli.WorldBorder + WorldBorder + 1.8.0 + + + com.pgcraft + SpectatorPlus + B3.0-SNAPSHOT + + + org.dynmap + dynmap-api + 1.8 + + + com.comphenix.protocol + ProtocolLib + 3.6.4 + + + org.mcstats.bukkit + metrics-lite + R8-SNAPSHOT + compile + + + junit + junit + 4.8.2 + jar + test + + + org.powermock + powermock-module-junit4 + 1.4.9 + jar + test + + + org.powermock + powermock-api-mockito + 1.4.9 + jar + test + + + org.javassist + javassist + 3.18.2-GA + test + + diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java b/src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java new file mode 100644 index 0000000..35d2e8f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java @@ -0,0 +1,364 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded; + +import eu.carrade.amaury.UHCReloaded.borders.BorderManager; +import eu.carrade.amaury.UHCReloaded.commands.UHCommandExecutor; +import eu.carrade.amaury.UHCReloaded.game.UHGameManager; +import eu.carrade.amaury.UHCReloaded.integration.UHDynmapIntegration; +import eu.carrade.amaury.UHCReloaded.integration.UHProtocolLibIntegrationWrapper; +import eu.carrade.amaury.UHCReloaded.integration.UHSpectatorPlusIntegration; +import eu.carrade.amaury.UHCReloaded.integration.UHWorldBorderIntegration; +import eu.carrade.amaury.UHCReloaded.listeners.BeforeGameListener; +import eu.carrade.amaury.UHCReloaded.listeners.CraftingListener; +import eu.carrade.amaury.UHCReloaded.listeners.GameListener; +import eu.carrade.amaury.UHCReloaded.listeners.GameplayListener; +import eu.carrade.amaury.UHCReloaded.listeners.SpawnsListener; +import eu.carrade.amaury.UHCReloaded.misc.Freezer; +import eu.carrade.amaury.UHCReloaded.misc.MOTDManager; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import eu.carrade.amaury.UHCReloaded.misc.PlayerListHeaderFooterManager; +import eu.carrade.amaury.UHCReloaded.misc.RulesManager; +import eu.carrade.amaury.UHCReloaded.misc.RuntimeCommandsExecutor; +import eu.carrade.amaury.UHCReloaded.recipes.RecipesManager; +import eu.carrade.amaury.UHCReloaded.scoreboard.ScoreboardManager; +import eu.carrade.amaury.UHCReloaded.spawns.SpawnsManager; +import eu.carrade.amaury.UHCReloaded.spectators.SpectatorsManager; +import eu.carrade.amaury.UHCReloaded.task.UpdateTimerTask; +import eu.carrade.amaury.UHCReloaded.teams.TeamChatManager; +import eu.carrade.amaury.UHCReloaded.teams.TeamManager; +import eu.carrade.amaury.UHCReloaded.timers.TimerManager; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.i18n.I18n; +import fr.zcraft.zlib.components.scoreboard.SidebarScoreboard; +import fr.zcraft.zlib.core.ZLib; +import fr.zcraft.zlib.core.ZPlugin; +import org.bukkit.entity.Player; +import org.mcstats.MetricsLite; + +import java.io.IOException; +import java.util.Locale; + + +public class UHCReloaded extends ZPlugin +{ + private static UHCReloaded instance; + + private TeamManager teamManager = null; + private SpawnsManager spawnsManager = null; + private UHGameManager gameManager = null; + private SpectatorsManager spectatorsManager = null; + private ScoreboardManager scoreboardManager = null; + private MOTDManager motdManager = null; + private RulesManager rulesManager = null; + private PlayerListHeaderFooterManager playerListHeaderFooterManager = null; + private BorderManager borderManager = null; + private RecipesManager recipesManager = null; + private TeamChatManager teamChatManager = null; + private TimerManager timerManager = null; + + private RuntimeCommandsExecutor runtimeCommandsExecutor = null; + + private Freezer freezer = null; + + private UHWorldBorderIntegration wbintegration = null; + private UHSpectatorPlusIntegration spintegration = null; + private UHDynmapIntegration dynmapintegration = null; + private UHProtocolLibIntegrationWrapper protocollibintegrationwrapper = null; + + + @Override + public void onEnable() + { + instance = this; + + this.saveDefaultConfig(); + + loadComponents(SidebarScoreboard.class, Gui.class, I18n.class, UHConfig.class, OfflinePlayersLoader.class); + + final String langInConfig = UHConfig.LANG.get(); + if (langInConfig == null || langInConfig.isEmpty()) + { + //i18n = new eu.carrade.amaury.UHCReloaded.i18n.I18n(this); + I18n.useDefaultPrimaryLocale(); + } + else + { + //i18n = new eu.carrade.amaury.UHCReloaded.i18n.I18n(this, langInConfig); + I18n.setPrimaryLocale(Locale.forLanguageTag(langInConfig)); + } + + I18n.setFallbackLocale(Locale.US); + + + wbintegration = new UHWorldBorderIntegration(); + spintegration = new UHSpectatorPlusIntegration(this); + dynmapintegration = new UHDynmapIntegration(this); + + // Needed to avoid a NoClassDefFoundError. + // I don't like this way of doing this, but else, the plugin will not load without ProtocolLib. + protocollibintegrationwrapper = new UHProtocolLibIntegrationWrapper(this); + + + spectatorsManager = SpectatorsManager.getInstance(); + teamManager = new TeamManager(this); + gameManager = new UHGameManager(this); + spawnsManager = new SpawnsManager(this); + borderManager = new BorderManager(this); + recipesManager = new RecipesManager(this); + teamChatManager = new TeamChatManager(this); + timerManager = new TimerManager(); + + runtimeCommandsExecutor = new RuntimeCommandsExecutor(this); + + freezer = new Freezer(this); + + scoreboardManager = new ScoreboardManager(this); + motdManager = new MOTDManager(this); + rulesManager = new RulesManager(); + playerListHeaderFooterManager = new PlayerListHeaderFooterManager(); + + UHCommandExecutor executor = new UHCommandExecutor(this); + for (String commandName : getDescription().getCommands().keySet()) + { + getCommand(commandName).setExecutor(executor); + getCommand(commandName).setTabCompleter(executor); + } + + ZLib.registerEvents(new GameListener(this)); + ZLib.registerEvents(new GameplayListener(this)); + ZLib.registerEvents(new CraftingListener(this)); + ZLib.registerEvents(new SpawnsListener()); + ZLib.registerEvents(new BeforeGameListener()); + + // The freezer listener is registered by the freezer when it is needed. + + recipesManager.registerRecipes(); + gameManager.initEnvironment(); + + motdManager.updateMOTDBeforeStart(); + + // In case of reload + for (Player player : getServer().getOnlinePlayers()) + { + gameManager.initPlayer(player); + } + + // Imports spawnpoints from the config. + this.spawnsManager.importSpawnPointsFromConfig(); + + // Imports teams from the config. + this.teamManager.importTeamsFromConfig(); + + // Starts the task that updates the timers. + // Started here, so a timer can be displayed before the start of the game + // (example: countdown before the start). + new UpdateTimerTask(this).runTaskTimer(this, 20l, 20l); + + // Schedule commands + runtimeCommandsExecutor.registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_SERVER_START); + + // Launch metrics + if (UHConfig.METRICS.get()) + { + try + { + MetricsLite metrics = new MetricsLite(this); + metrics.start(); + } + catch (IOException e) + { + // Failed to submit the stats :-( + } + } + else + { + getLogger().info("Metrics disabled for this plugin in the configuration: nothing was sent."); + } + + getLogger().info(I.t("Ultra Hardcore plugin loaded.")); + } + + /** + * Returns the team manager. + */ + public TeamManager getTeamManager() + { + return teamManager; + } + + /** + * Returns the game manager. + */ + public UHGameManager getGameManager() + { + return gameManager; + } + + /** + * @return the spectators manager. + */ + public SpectatorsManager getSpectatorsManager() + { + return spectatorsManager; + } + + /** + * Returns the scoreboard manager. + */ + public ScoreboardManager getScoreboardManager() + { + return scoreboardManager; + } + + /** + * Returns the MOTD manager. + */ + public MOTDManager getMOTDManager() + { + return motdManager; + } + + /** + * @return the rules manager. + */ + public RulesManager getRulesManager() + { + return rulesManager; + } + + /** + * Returns the players list's headers & footers manager. + */ + public PlayerListHeaderFooterManager getPlayerListHeaderFooterManager() + { + return playerListHeaderFooterManager; + } + + /** + * Returns the spawns points manager. + */ + public SpawnsManager getSpawnsManager() + { + return spawnsManager; + } + + /** + * Returns the border manager. + */ + public BorderManager getBorderManager() + { + return borderManager; + } + + /** + * Returns the recipe manager. + */ + public RecipesManager getRecipesManager() + { + return recipesManager; + } + + /** + * Returns the team-chat manager. + */ + public TeamChatManager getTeamChatManager() + { + return teamChatManager; + } + + /** + * Returns the timer manager. + */ + public TimerManager getTimerManager() + { + return timerManager; + } + + /** + * Returns the manager used to manage the commands executed after the start/the end of the + * game (or any other moment using the generic API). + */ + public RuntimeCommandsExecutor getRuntimeCommandsExecutor() + { + return runtimeCommandsExecutor; + } + + /** + * Returns the freezer. + */ + public Freezer getFreezer() + { + return freezer; + } + + /** + * Returns the representation of the WorldBorder integration in the plugin. + */ + public UHWorldBorderIntegration getWorldBorderIntegration() + { + return wbintegration; + } + + /** + * Returns the representation of the SpectatorPlus integration in the plugin. + */ + public UHSpectatorPlusIntegration getSpectatorPlusIntegration() + { + return spintegration; + } + + /** + * Returns the representation of the dynmap integration in the plugin. + */ + public UHDynmapIntegration getDynmapIntegration() + { + return dynmapintegration; + } + + /** + * Returns a wrapper of the representation of the ProtocolLib integration in the plugin. + */ + public UHProtocolLibIntegrationWrapper getProtocolLibIntegrationWrapper() + { + return protocollibintegrationwrapper; + } + + /** + * Returns the plugin's instance. + */ + public static UHCReloaded get() + { + return instance; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/UHConfig.java b/src/main/java/eu/carrade/amaury/UHCReloaded/UHConfig.java new file mode 100644 index 0000000..a47e236 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/UHConfig.java @@ -0,0 +1,595 @@ +package eu.carrade.amaury.UHCReloaded; + +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.game.Cage; +import eu.carrade.amaury.UHCReloaded.teams.TeamManager; +import eu.carrade.amaury.UHCReloaded.utils.UHSound; +import fr.zcraft.zlib.components.configuration.Configuration; +import fr.zcraft.zlib.components.configuration.ConfigurationItem; +import fr.zcraft.zlib.components.configuration.ConfigurationList; +import fr.zcraft.zlib.components.configuration.ConfigurationMap; +import fr.zcraft.zlib.components.configuration.ConfigurationSection; +import fr.zcraft.zlib.components.configuration.ConfigurationValueHandlers; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.util.Vector; + +import static fr.zcraft.zlib.components.configuration.ConfigurationItem.*; + + +public class UHConfig extends Configuration +{ + static public final ConfigurationItem LANG = item("lang", ""); + static public final ConfigurationItem METRICS = item("metrics", true); + + static public final EpisodesSection EPISODES = section("episodes", EpisodesSection.class); + + static public class EpisodesSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem LENGTH = item("length", "20:00"); + public final ConfigurationItem TITLE = item("title", true); + } + + static public final MapSection MAP = section("map", MapSection.class); + + static public class MapSection extends ConfigurationSection + { + public final ConfigurationItem SIZE = item("size", 2000); + public final ConfigurationItem SHAPE = item("shape", MapShape.SQUARED); + + public final WallSection WALL = section("wall", WallSection.class); + + static public class WallSection extends ConfigurationSection + { + public final ConfigurationItem HEIGHT = item("height", 128); + + public final BlockSection BLOCK = section("block", BlockSection.class); + + static public class BlockSection extends ConfigurationSection + { + public final ConfigurationItem REPLACE_AIR = item("replaceAir", Material.GLASS); + public final ConfigurationItem REPLACE_SOLID = item("replaceSolid", Material.BEDROCK); + } + } + + public final BorderSection BORDER = section("border", BorderSection.class); + + static public class BorderSection extends ConfigurationSection + { + public final ConfigurationItem MOTOR = item("motor", "vanilla"); + public final ConfigurationItem DAMAGES_BUFFER = item("damagesBuffer", 5d); + public final ConfigurationItem DAMAGES_AMOUNT = item("damagesAmount", 0.2); + public final ConfigurationItem WARNING_DISTANCE = item("warningDistance", 5); + + public final ShrinkingSection SHRINKING = section("shrinking", ShrinkingSection.class); + + static public class ShrinkingSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", false); + public final ConfigurationItem STARTS_AFTER = item("startsAfter", "30:00"); + public final ConfigurationItem SHRINKS_DURING = item("shrinksDuring", "2:00:00"); + public final ConfigurationItem DIAMETER_AFTER_SHRINK = item("diameterAfterShrink", 200); + } + + public final ConfigurationItem WARNING_INTERVAL = item("warningInterval", 90); + } + + public final SpawnPointsSection SPAWN_POINTS = section("spawnPoints", SpawnPointsSection.class); + + static public class SpawnPointsSection extends ConfigurationSection + { + public final ConfigurationItem DONT_GENERATE_ABOVE_WATER = item("dontGenerateAboveWater", true); + } + } + + static public final DaylightCycleSection DAYLIGHT_CYCLE = section("daylightCycle", DaylightCycleSection.class); + + static public class DaylightCycleSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", false); + public final ConfigurationItem TIME = item("time", 6000l); + } + + static public final ScoreboardSection SCOREBOARD = section("scoreboard", ScoreboardSection.class); + + static public class ScoreboardSection extends ConfigurationSection + { + public final ConfigurationItem TITLE = item("title", "Kill the Patrick"); + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem EPISODE = item("episode", true); + public final ConfigurationItem PLAYERS = item("players", true); + public final ConfigurationItem TEAMS = item("teams", true); + + public final OwnTeamSection OWN_TEAM = section("ownTeam", OwnTeamSection.class); + + static public class OwnTeamSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + + public final TitleSection TITLE = section("title", TitleSection.class); + + static public class TitleSection extends ConfigurationSection + { + public final ConfigurationItem COLOR = item("color", ""); + public final ConfigurationItem USE_TEAM_NAME = item("useTeamName", false); + } + + public final ContentSection CONTENT = section("content", ContentSection.class); + + static public class ContentSection extends ConfigurationSection + { + public final ConfigurationItem DISPLAY_HEARTS = item("displayHearts", true); + public final ConfigurationItem COLOR_NAME = item("colorName", false); + public final ConfigurationItem STRIKE_DEAD_PLAYERS = item("strikeDeadPlayers", false); + + public final LoginStateSection LOGIN_STATE = section("loginState", LoginStateSection.class); + + static public class LoginStateSection extends ConfigurationSection + { + public final ConfigurationItem ITALIC = item("italic", true); + public final ConfigurationItem SUFFIX = item("suffix", "➥"); + } + + public final DisplayMetPlayersOnlySection DISPLAY_MET_PLAYERS_ONLY = section("displayMetPlayersOnly", DisplayMetPlayersOnlySection.class); + + static public class DisplayMetPlayersOnlySection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", false); + public final ConfigurationItem DISPLAYED_WHEN_CLOSER_THAN = item("displayedWhenCloserThan", 10d); + } + } + } + + public final BorderSection BORDER = section("border", BorderSection.class); + + static public class BorderSection extends ConfigurationSection + { + public final ConfigurationItem DISPLAYED = item("displayed", true); + public final ConfigurationItem DISPLAY_DIAMETER = item("displayDiameter", false); + } + + public final ConfigurationItem KILLS = item("kills", true); + public final ConfigurationItem TIMER = item("timer", true); + public final ConfigurationItem FREEZE_STATUS = item("freezeStatus", true); + public final ConfigurationItem HEALTH = item("health", true); + } + + static public final PlayersListSection PLAYERS_LIST = section("playersList", PlayersListSection.class); + + static public class PlayersListSection extends ConfigurationSection + { + public final WaitingTimeSection WAITING_TIME = section("waitingTime", WaitingTimeSection.class); + + static public class WaitingTimeSection extends ConfigurationSection + { + public final ConfigurationItem HEADER = item("header", "{title}"); + public final ConfigurationItem FOOTER = item("footer", ""); + } + + public final InGameTimeSection IN_GAME_TIME = section("inGameTime", InGameTimeSection.class); + + static public class InGameTimeSection extends ConfigurationSection + { + public final ConfigurationItem HEADER = item("header", "{title}"); + public final ConfigurationItem FOOTER = item("footer", "§a{episodeText} §7- §a{playersText} §7- §a{teamsText}"); + } + } + + static public final MotdSection MOTD = section("motd", MotdSection.class); + + static public class MotdSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", false); + public final ConfigurationItem DISPLAY_MATCH_NAME = item("displayMatchName", true); + public final ConfigurationItem MATCH_NAME_PREFIX = item("matchNamePrefix", ""); + } + + static public final ConfigurationItem TELEPORT_TO_SPAWN_IF_NOT_STARTED = item("teleportToSpawnIfNotStarted", true); + + static public final AchievementsSection ACHIEVEMENTS = section("achievements", AchievementsSection.class); + + static public class AchievementsSection extends ConfigurationSection + { + public final ConfigurationItem RESET_ACHIEVEMENTS_AT_STARTUP = item("resetAchievementsAtStartup", true); + public final ConfigurationItem DISABLE_ACHIEVEMENTS_BEFORE_START = item("disableAchievementsBeforeStart", true); + } + + static public final StatisticsSection STATISTICS = section("statistics", StatisticsSection.class); + + static public class StatisticsSection extends ConfigurationSection + { + public final ConfigurationItem DISABLE_STATISTICS_BEFORE_START = item("disableStatisticsBeforeStart", true); + } + + static public final BeforeStartSection BEFORE_START = section("before-start", BeforeStartSection.class); + + static public class BeforeStartSection extends ConfigurationSection + { + public final InventorySection INVENTORY = section("inventory", InventorySection.class); + + static public class InventorySection extends ConfigurationSection + { + public final ConfigurationItem CLEAR = item("clear", true); + public final ConfigurationItem PREVENT_USAGE = item("preventUsage", true); + public final ConfigurationItem ALLOW_FOR_BUILDERS = item("allowForBuilders", true); + } + + public final TeamSelectorSection TEAM_SELECTOR = section("teamSelector", TeamSelectorSection.class); + + static public class TeamSelectorSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem ITEM = item("item", Material.NETHER_STAR); + } + + public final ConfigurationItem TEAM_IN_ACTION_BAR = item("teamInActionBar", true); + + public final ConfigurationItem ENABLE_PVP = item("enablePVP", false); + } + + static public final StartSection START = section("start", StartSection.class); + + static public class StartSection extends ConfigurationSection + { + public final SlowSection SLOW = section("slow", SlowSection.class); + + static public class SlowSection extends ConfigurationSection + { + public final ConfigurationItem DELAY_BETWEEN_TP = item("delayBetweenTP", 3l); + public final ConfigurationItem BROADCAST_PROGRESS = item("broadcastProgress", true); + + public final CagesSection CAGES = section("cages", CagesSection.class); + + static public class CagesSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem TYPE = item("type", Cage.CageType.TEAM_COLOR_TRANSPARENT); + public final ConfigurationItem CUSTOM_BLOCK = item("customBlock", Material.BARRIER); + public final ConfigurationItem BUILD_CEILING = item("buildCeiling", false); + public final ConfigurationItem VISIBLE_WALLS = item("visibleWalls", false); + public final ConfigurationItem RADIUS = item("radius", 1); + public final ConfigurationItem HEIGHT = item("height", 3); + } + } + + public final SoundSection SOUND = section("sound", SoundSection.class); + + public final ConfigurationItem DISPLAY_TITLE = item("displayTitle", true); + public final ConfigurationItem GRACE_PERIOD = item("gracePeriod", "00:30"); + public final ConfigurationItem BROADCAST_GRACE_END = item("broadcastGraceEnd", true); + public final ConfigurationItem PEACE_PERIOD = item("peacePeriod", "00"); + public final ConfigurationItem SURFACE_MOBS_FREE_PERIOD = item("surfaceMobsFreePeriod", "15:00"); + } + + static public final DeathSection DEATH = section("death", DeathSection.class); + + static public class DeathSection extends ConfigurationSection + { + public final MessagesSection MESSAGES = section("messages", MessagesSection.class); + + static public class MessagesSection extends ConfigurationSection + { + public final ConfigurationItem NOTIFY_IF_TEAM_HAS_FALLEN = item("notifyIfTeamHasFallen", true); + public final ConfigurationItem DEATH_MESSAGES_FORMAT = item("deathMessagesFormat", "§6"); + public final ConfigurationItem TEAM_DEATH_MESSAGES_FORMAT = item("teamDeathMessagesFormat", "§6"); + } + + public final KickSection KICK = section("kick", KickSection.class); + + static public class KickSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", false); + public final ConfigurationItem TIME = item("time", 30); + public final ConfigurationItem ALLOW_RECONNECT = item("allow-reconnect", true); + } + + public final HeadSection HEAD = section("head", HeadSection.class); + + static public class HeadSection extends ConfigurationSection + { + public final ConfigurationItem DROP = item("drop", true); + public final ConfigurationItem PVP_ONLY = item("pvpOnly", false); + } + + public final GiveXpToKillerSection GIVE_XP_TO_KILLER = section("give-xp-to-killer", GiveXpToKillerSection.class); + + static public class GiveXpToKillerSection extends ConfigurationSection + { + public final ConfigurationItem LEVELS = item("levels", 2); + public final ConfigurationItem ONLY_OTHER_TEAM = item("onlyOtherTeam", true); + } + + public final AnnouncementsSection ANNOUNCEMENTS = section("announcements", AnnouncementsSection.class); + + static public class AnnouncementsSection extends ConfigurationSection + { + public final ConfigurationItem LIGHTNING_STRIKE = item("lightning-strike", false); + public final SoundSection SOUND = section("sound", SoundSection.class); + } + } + + static public final ConfigurationItem COLORIZE_CHAT = item("colorizeChat", true); + + static public final GameplayChangesSection GAMEPLAY_CHANGES = section("gameplay-changes", GameplayChangesSection.class); + + static public class GameplayChangesSection extends ConfigurationSection + { + public final ConfigurationItem NATURAL_REGENERATION = item("naturalRegeneration", false); + public final ConfigurationItem WEATHER = item("weather", true); + public final ConfigurationItem REPLACE_GHAST_TEARS_WITH_GOLD = item("replaceGhastTearsWithGold", true); + public final ConfigurationItem CRAFT_GOLDEN_MELON_WITH_GOLD_BLOCK = item("craftGoldenMelonWithGoldBlock", true); + + public final CraftGoldenAppleFromHeadSection CRAFT_GOLDEN_APPLE_FROM_HEAD = section("craftGoldenAppleFromHead", CraftGoldenAppleFromHeadSection.class); + + static public class CraftGoldenAppleFromHeadSection extends ConfigurationSection + { + public final FromHumanSection FROM_HUMAN = section("fromHuman", FromHumanSection.class); + + static public class FromHumanSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", true); + public final ConfigurationItem NUMBER_CRAFTED = item("numberCrafted", 2); + public final ConfigurationItem ADD_LORE = item("addLore", true); + public final ConfigurationItem CRAFT_NOTCH_APPLE = item("craftNotchApple", false); + } + + + public final FromWitherSection FROM_WITHER = section("fromWither", FromWitherSection.class); + + static public class FromWitherSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", true); + public final ConfigurationItem NUMBER_CRAFTED = item("numberCrafted", 1); + public final ConfigurationItem ADD_LORE = item("addLore", true); + public final ConfigurationItem CRAFT_NOTCH_APPLE = item("craftNotchApple", false); + } + } + + public final GoldenAppleSection GOLDEN_APPLE = section("goldenApple", GoldenAppleSection.class); + + static public class GoldenAppleSection extends ConfigurationSection + { + public final RegenerationSection REGENERATION = section("regeneration", RegenerationSection.class); + + static public class RegenerationSection extends ConfigurationSection + { + public final ConfigurationItem NORMAL = item("normal", 4); + public final ConfigurationItem NOTCH = item("notch", 180); + public final ConfigurationItem FROM_NORMAL_HEAD = item("fromNormalHead", 4); + public final ConfigurationItem FROM_NOTCH_HEAD = item("fromNotchHead", 180); + } + + public final ConfigurationItem DISABLE_NOTCH_APPLES = item("disableNotchApples", false); + } + + public final ConfigurationItem DISABLE_ENDERPEARLS_DAMAGES = item("disableEnderpearlsDamages", true); + public final ConfigurationItem DISABLE_LEVEL_II_POTIONS = item("disableLevelIIPotions", false); + + public final WitchSection WITCH = section("witch", WitchSection.class); + + static public class WitchSection extends ConfigurationSection + { + public final ConfigurationItem DISABLE_NATURAL_SPAWN = item("disableNaturalSpawn", false); + public final ConfigurationItem DISABLE_LIGHTNING_SPAWN = item("disableLightningSpawn", false); + } + + public final RabbitSection RABBIT = section("rabbit", RabbitSection.class); + + static public class RabbitSection extends ConfigurationSection + { + public final ConfigurationItem KILLER_RABBIT_SPAWN = item("killerRabbitSpawn", true); + public final ConfigurationItem KILLER_RABBIT_SPAWN_PROBABILITY = item("killerRabbitSpawnProbability", 0.05); + public final ConfigurationItem KILLER_RABBIT_NAME = item("killerRabbitName", "The Killer Rabbit of Caerbannog"); + } + + public final CompassSection COMPASS = section("compass", CompassSection.class); + + static public class CompassSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem RECIPE = item("recipe", "medium"); + } + } + + static public final TeamsOptionsSection TEAMS_OPTIONS = section("teams-options", TeamsOptionsSection.class); + + static public class TeamsOptionsSection extends ConfigurationSection + { + public final ConfigurationItem CAN_SEE_FRIENDLY_INVISIBLES = item("canSeeFriendlyInvisibles", true); + public final ConfigurationItem ALLOW_FRIENDLY_FIRE = item("allowFriendlyFire", true); + public final ConfigurationItem MAX_PLAYERS_PER_TEAM = item("maxPlayersPerTeam", 0); + public final ConfigurationItem RANDOM_COLORS = item("randomColors", true); + + public final BannerSection BANNER = section("banner", BannerSection.class); + + static public class BannerSection extends ConfigurationSection + { + public final ShapeSection SHAPE = section("shape", ShapeSection.class); + + static public class ShapeSection extends ConfigurationSection + { + public final ConfigurationItem WRITE_LETTER = item("writeLetter", true); + public final ConfigurationItem ADD_BORDER = item("addBorder", true); + } + + public final GiveSection GIVE = section("give", GiveSection.class); + + static public class GiveSection extends ConfigurationSection + { + public final ConfigurationItem PLACE_ON_SPAWN = item("placeOnSpawn", true); + public final ConfigurationItem GIVE_IN_HOTBAR = item("giveInHotbar", false); + public final ConfigurationItem GIVE_IN_HEAD = item("giveInHead", false); + } + + public final ShieldSection SHIELDS = section("shields", ShieldSection.class); + + static public class ShieldSection extends ConfigurationSection + { + public final ConfigurationItem ADD_ON_SHIELDS = item("addOnShields", true); + } + } + + public final GuiSection GUI = section("gui", GuiSection.class); + + static public class GuiSection extends ConfigurationSection + { + public final ConfigurationItem DISPLAY_PLAYERS_IN_TEAMS = item("displayPlayersInTeams", true); + public final ConfigurationItem AUTO_DISPLAY = item("autoDisplay", true); + public final ConfigurationItem DELAY = item("delay", 4); + } + + public final ChestGuiSection CHEST_GUI = section("chestGui", ChestGuiSection.class); + + static public class ChestGuiSection extends ConfigurationSection + { + public final DisplaySection DISPLAY = section("display", DisplaySection.class); + + static public class DisplaySection extends ConfigurationSection + { + public final ConfigurationItem TEAM_ITEM = item("teamItem", "banner"); + public final ConfigurationItem GLOW_ON_SELECTED_TEAM = item("glowOnSelectedTeam", true); + } + } + + public final TeamChatSection TEAM_CHAT = section("teamChat", TeamChatSection.class); + + static public class TeamChatSection extends ConfigurationSection + { + public final ConfigurationItem DISABLE_LOCK_ON_DEATH = item("disableLockOnDeath", true); + public final ConfigurationItem LOG = item("log", false); + } + } + + static public final HardcoreHeartsSection HARDCORE_HEARTS = section("hardcore-hearts", HardcoreHeartsSection.class); + + static public class HardcoreHeartsSection extends ConfigurationSection + { + public final ConfigurationItem DISPLAY = item("display", true); + public final ConfigurationItem RESPAWN_MESSAGE = item("respawnMessage", false); + } + + static public final AutoRespawnSection AUTO_RESPAWN = section("auto-respawn", AutoRespawnSection.class); + + static public class AutoRespawnSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", true); + public final ConfigurationItem DELAY = item("delay", 6); + } + + static public final FinishSection FINISH = section("finish", FinishSection.class); + + static public class FinishSection extends ConfigurationSection + { + public final AutoSection AUTO = section("auto", AutoSection.class); + + static public class AutoSection extends ConfigurationSection + { + public final ConfigurationItem DO = item("do", true); + public final ConfigurationItem TIME_AFTER_LAST_DEATH = item("timeAfterLastDeath", 3); + } + + public final ConfigurationItem MESSAGE = item("message", true); + public final ConfigurationItem TITLE = item("title", true); + + public final FireworksSection FIREWORKS = section("fireworks", FireworksSection.class); + + static public class FireworksSection extends ConfigurationSection + { + public final ConfigurationItem ENABLED = item("enabled", true); + public final ConfigurationItem DURATION = item("duration", 10l); + public final ConfigurationItem AREA_SIZE = item("areaSize", 6d); + } + } + + static public final DynmapSection DYNMAP = section("dynmap", DynmapSection.class); + + static public class DynmapSection extends ConfigurationSection + { + public final ConfigurationItem SHOW_SPAWN_LOCATIONS = item("showSpawnLocations", true); + public final ConfigurationItem SHOW_DEATH_LOCATIONS = item("showDeathLocations", true); + } + + static public final ConfigurationItem SPECTATOR_MODE_WHEN_NEW_PLAYER_JOIN_AFTER_START = item("spectatorModeWhenNewPlayerJoinAfterStart", true); + + static public final RulesSection RULES = section("rules", RulesSection.class); + + static public class RulesSection extends ConfigurationSection + { + public final DisplaySection DISPLAY = section("display", DisplaySection.class); + + static public class DisplaySection extends ConfigurationSection + { + public final ConfigurationItem ON_JOIN = item("onJoin", false); + public final ConfigurationItem ON_START = item("onStart", true); + } + + public final ConfigurationList RULES = list("rules", String.class); + } + + static public final CommandsSection COMMANDS = section("commands", CommandsSection.class); + + static public class CommandsSection extends ConfigurationSection + { + public final ConfigurationList EXECUTE_SERVER_START = list("execute-server-start", String.class); + public final ConfigurationList EXECUTE_START = list("execute-start", String.class); + public final ConfigurationList EXECUTE_END = list("execute-end", String.class); + } + + static public final ProtipsSection PROTIPS = section("protips", ProtipsSection.class); + + static public class ProtipsSection extends ConfigurationSection + { + public final SoundSection SOUND = section("sound", SoundSection.class); + + public final TeamchatSection TEAMCHAT = section("teamchat", TeamchatSection.class); + + static public class TeamchatSection extends ConfigurationSection + { + public final ConfigurationItem USE_T_COMMAND = item("useTCommand", true); + public final ConfigurationItem LOCK = item("lock", true); + public final ConfigurationItem USE_G_COMMAND = item("useGCommand", true); + } + + public final CraftsSection CRAFTS = section("crafts", CraftsSection.class); + + static public class CraftsSection extends ConfigurationSection + { + public final ConfigurationItem GOLDEN_HEAD = item("goldenHead", true); + public final ConfigurationItem COMPASS_EASY = item("compassEasy", true); + public final ConfigurationItem COMPASS_MEDIUM = item("compassMedium", true); + public final ConfigurationItem COMPASS_HARD = item("compassHard", true); + public final ConfigurationItem GLISTERING_MELON = item("glisteringMelon", true); + public final ConfigurationItem NO_ENCH_GOLDEN_APPLE = item("noEnchGoldenApple", true); + } + + public final StartSection START = section("start", StartSection.class); + + static public class StartSection extends ConfigurationSection + { + public final ConfigurationItem INVINCIBILITY = item("invincibility", true); + } + } + + static public final ConfigurationList SPAWN_POINTS = list("spawnpoints", Vector.class); + static public final ConfigurationList TEAMS = list("teams", String.class); + static public final ConfigurationMap TEAM_BANNERS = map("teambanners", String.class, BannerMeta.class); + + /* ** Helper sub-sections ** */ + + static public class SoundSection extends ConfigurationSection + { + public final ConfigurationItem NAME = item("name", Sound.class); + public final ConfigurationItem VOLUME = item("volume", 1); + public final ConfigurationItem PITCH = item("pitch", 1); + } + + /* ** Helper value handlers ** */ + + static + { + ConfigurationValueHandlers.registerHandlers(TeamManager.class); + ConfigurationValueHandlers.registerHandlers(UHSound.class); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java new file mode 100644 index 0000000..2344924 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java @@ -0,0 +1,437 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.borders; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.borders.exceptions.CannotGenerateWallsException; +import eu.carrade.amaury.UHCReloaded.borders.generators.WallGenerator; +import eu.carrade.amaury.UHCReloaded.borders.worldborders.WorldBorder; +import eu.carrade.amaury.UHCReloaded.task.BorderWarningTask; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.PluginLogger; +import fr.zcraft.zlib.tools.runners.RunTask; +import fr.zcraft.zlib.tools.text.Titles; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashSet; +import java.util.Set; + + +public class BorderManager +{ + private final boolean BORDER_SHRINKING; + private final long BORDER_SHRINKING_STARTS_AFTER; + private final long BORDER_SHRINKING_DURATION; + private final double BORDER_SHRINKING_FINAL_SIZE; + + private UHCReloaded p = null; + + private WorldBorder border = null; + + private Integer warningSize = 0; + private BukkitRunnable warningTask = null; + + private Boolean warningFinalTimeEnabled = false; + private String warningTimerName = null; + private CommandSender warningSender = null; + + private MapShape mapShape = null; + + + public BorderManager(UHCReloaded plugin) + { + p = plugin; + + /// The name of the warning timer displaying the time left before the next border + warningTimerName = I.t("Border shrinking"); + + mapShape = UHConfig.MAP.SHAPE.get(); + if (mapShape == null) + { + PluginLogger.warning("Invalid shape '" + UHConfig.MAP.SHAPE.get() + "'; using 'squared' instead."); + mapShape = MapShape.SQUARED; + } + + + World world = UHUtils.getOverworld(); + + if (world == null) + { + world = Bukkit.getWorlds().get(0); + PluginLogger.warning("Cannot find overworld! Using the world '{0}' instead (environment: {1}).", world.getName(), world.getEnvironment()); + } + + border = WorldBorder.getInstance(world, UHConfig.MAP.BORDER.MOTOR.get(), mapShape); + + border.setShape(mapShape); + border.setCenter(world.getSpawnLocation()); + border.setDiameter(UHConfig.MAP.SIZE.get()); + + border.init(); + + PluginLogger.info("Using {0} to set the world border.", border.getClass().getSimpleName()); + + + BORDER_SHRINKING = UHConfig.MAP.BORDER.SHRINKING.ENABLED.get(); + BORDER_SHRINKING_STARTS_AFTER = UHUtils.string2Time(UHConfig.MAP.BORDER.SHRINKING.STARTS_AFTER.get(), 30*60); // Seconds + BORDER_SHRINKING_DURATION = UHUtils.string2Time(UHConfig.MAP.BORDER.SHRINKING.SHRINKS_DURING.get(), 60*60*2); // Same + BORDER_SHRINKING_FINAL_SIZE = UHConfig.MAP.BORDER.SHRINKING.DIAMETER_AFTER_SHRINK.get(); + } + + /** + * Sets the shape of the map. Updates the WorldBorder too. + * + * @param shape The shape. + */ + public void setMapShape(MapShape shape) + { + this.mapShape = shape; + border.setShape(shape); + } + + /** + * Returns the current shape of the map. + * + * @return The shape. + */ + public MapShape getMapShape() + { + return mapShape; + } + + /** + * @return The WorldBorder proxy to set the border in-game. + */ + public WorldBorder getBorderProxy() + { + return border; + } + + /** + * Checks if a given location is inside the border with the given diameter. + * The check is performed for a circular or squared border, following the configuration. + * + * @param location The location to check. + * @param diameter The diameter of the checked border. + * + * @return {@code true} if inside. + */ + public boolean isInsideBorder(Location location, double diameter) + { + // The nether/end are not limited. + return !location.getWorld().getEnvironment().equals(Environment.NORMAL) || mapShape.getShape().isInsideBorder(location, diameter, location.getWorld().getSpawnLocation()); + } + + /** + * Checks if a given location is inside the border with the current diameter. + * The check is performed for a circular or squared border, following the configuration. + * + * @param location The location to check. + * @return {@code true} if inside. + */ + public boolean isInsideBorder(Location location) + { + return this.isInsideBorder(location, getCurrentBorderDiameter()); + } + + /** + * Returns the distance from the location to the border, if the location is outside this border. + * If it is inside, or in another world, returns 0. + * + * @param location The location to check. + * @param diameter The diameter of the checked border. + * + * @return The distance, or 0 if the player is either inside the border or not in the world. + */ + public double getDistanceToBorder(Location location, double diameter) + { + return mapShape.getShape().getDistanceToBorder(location, diameter, location.getWorld().getSpawnLocation()); + } + + + /** + * Returns a list of the players outside a border with the given diameter. + * The check is performed for a circular or squared border, following the configuration. + * + * @param diameter The diameter of the checked border. + * @return A list of players out of the given diameter. + */ + public Set getPlayersOutside(int diameter) + { + HashSet playersOutside = new HashSet(); + + for (final Player player : p.getGameManager().getOnlineAlivePlayers()) + { + if (!isInsideBorder(player.getLocation(), diameter)) + { + playersOutside.add(player); + } + } + + return playersOutside; + } + + /** + * Returns the size of the future border, used in the warning messages sent to the + * players out of this future border. + * + * @return the future border diameter. + */ + public int getWarningSize() + { + return this.warningSize; + } + + /** + * @return true if there is currently a warning with a time left displayed. + */ + public boolean getWarningFinalTimeEnabled() + { + return this.warningFinalTimeEnabled; + } + + /** + * @return the sender of the last warning configured. + */ + public CommandSender getWarningSender() + { + return this.warningSender; + } + + /** + * Sets the size of the future border, used in the warning messages sent to the + * players out of this future border. + * + * This also starts the display of the warning messages, every 90 seconds by default + * (configurable, see config.yml, map.border.warningInterval). + * + * If timeLeft is not null, the time available for the players to go inside the future + * border is displayed in the warning message. + * + * @param diameter The future diameter. + * @param timeLeft The time available for the players to go inside the future border (minutes). + * @param sender The user who requested this change. + */ + public void setWarningSize(int diameter, int timeLeft, CommandSender sender) + { + cancelWarning(); + + this.warningSize = diameter; + + if (timeLeft != 0) + { + UHTimer timer = new UHTimer(this.warningTimerName); + timer.setDuration(timeLeft * 60); + + p.getTimerManager().registerTimer(timer); + + timer.start(); + } + + if (sender != null) + { + this.warningSender = sender; + } + + warningTask = new BorderWarningTask(p); + warningTask.runTaskTimer(p, 20L, 20L * p.getConfig().getInt("map.border.warningInterval", 90)); + } + + /** + * Sets the size of the future border, used in the warning messages sent to the + * players out of this future border. + * + * This also starts the display of the warning messages, every 90 seconds by default + * (configurable, see config.yml, map.border.warningInterval). + * + * @param diameter The diameter of the future border. + */ + public void setWarningSize(int diameter) + { + setWarningSize(diameter, 0, null); + } + + /** + * Returns the UHTimer object representing the countdown before the next border reduction. + * + *

Returns {@code null} if there isn't any countdown running currently.

+ * + * @return The timer. + */ + public UHTimer getWarningTimer() + { + return p.getTimerManager().getTimer(this.warningTimerName); + } + + /** + * Stops the display of the warning messages. + */ + public void cancelWarning() + { + if (warningTask != null) + { + try + { + warningTask.cancel(); + } + catch (IllegalStateException ignored) {} + } + + UHTimer timer = getWarningTimer(); + if (timer != null) + { + timer.stop(); + p.getTimerManager().unregisterTimer(timer); + } + } + + /** + * @return the current border diameter. + */ + public int getCurrentBorderDiameter() + { + return (int) border.getDiameter(); + } + + /** + * Changes the current border diameter. + * This also reconfigures the used world border. + * + * If WorldBorder is installed, all players out of this new border will be teleported inside the new one. + * Else, nothing will happens. + * + * @param diameter the new diameter. + */ + public void setCurrentBorderDiameter(int diameter) + { + cancelWarning(); + + border.setDiameter(diameter); + } + + + /** + * Sends a list of the players outside the given border to the specified sender. + * + * @param to The player/console to send the check. + * @param diameter The diameter of the border to be checked. + */ + public void sendCheckMessage(CommandSender to, int diameter) + { + Set playersOutside = getPlayersOutside(diameter); + + if (playersOutside.size() == 0) + { + to.sendMessage(I.t("{cs}All players are inside the given border.")); + } + else + { + to.sendMessage(I.t("{ci}There are {0} players outside the given border.", String.valueOf(playersOutside.size()))); + for (Player player : getPlayersOutside(diameter)) + { + double distance = getDistanceToBorder(player.getLocation(), diameter); + if (distance > 150) + { + to.sendMessage(I.t("{lightpurple} - {red}{0}{ci} (far away from the border)", player.getName())); + } + else if (distance > 25) + { + to.sendMessage(I.t("{lightpurple} - {yellow}{0}{ci} (close to the border)", player.getName())); + } + else + { + to.sendMessage(I.t("{lightpurple} - {green}{0}{ci} (very close to the border)", player.getName())); + } + } + } + } + + /** + * Generates the walls in the given world, following the current border configuration. + * + * @param world The world were the walls will be built in. + * @throws CannotGenerateWallsException + */ + public void generateWalls(World world) throws CannotGenerateWallsException + { + Integer wallHeight = UHConfig.MAP.WALL.HEIGHT.get(); + + Material wallBlockAir = UHConfig.MAP.WALL.BLOCK.REPLACE_AIR.get(); + Material wallBlockSolid = UHConfig.MAP.WALL.BLOCK.REPLACE_SOLID.get(); + + if (wallBlockAir == null || !wallBlockAir.isSolid() || wallBlockSolid == null || !wallBlockSolid.isSolid()) + { + throw new CannotGenerateWallsException("Cannot generate the walls: invalid blocks set in the config"); + } + + WallGenerator generator = mapShape.getWallGeneratorInstance(wallBlockAir, wallBlockSolid); + if (generator != null) + generator.build(world, getCurrentBorderDiameter(), wallHeight); + else + throw new CannotGenerateWallsException("Unable to load walls generator."); + } + + /** + * Schedules the automatic border reduction, if enabled in the configuration. + */ + public void scheduleBorderReduction() + { + if (BORDER_SHRINKING) + { + RunTask.later(new Runnable() { + @Override + public void run() + { + Integer secondsPerBlock = (int) Math.rint(BORDER_SHRINKING_DURATION / (border.getDiameter() - BORDER_SHRINKING_FINAL_SIZE)) * 2; + + border.setDiameter(BORDER_SHRINKING_FINAL_SIZE, BORDER_SHRINKING_DURATION); + + Titles.broadcastTitle(5, 30, 8, I.t("{red}Warning!"), I.t("{white}The border begins to shrink...")); + + Bukkit.broadcastMessage(I.t("{red}{bold}The border begins to shrink...")); + Bukkit.broadcastMessage(I.t("{gray}It will shrink by one block every {0} second(s) until {1} blocks in diameter.", secondsPerBlock, BORDER_SHRINKING_FINAL_SIZE)); + } + }, BORDER_SHRINKING_STARTS_AFTER * 20l); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/MapShape.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/MapShape.java new file mode 100644 index 0000000..ee22c5d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/MapShape.java @@ -0,0 +1,114 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders; + +import eu.carrade.amaury.UHCReloaded.borders.generators.CircularWallGenerator; +import eu.carrade.amaury.UHCReloaded.borders.generators.SquaredWallGenerator; +import eu.carrade.amaury.UHCReloaded.borders.generators.WallGenerator; +import eu.carrade.amaury.UHCReloaded.borders.shapes.CircularMapShape; +import eu.carrade.amaury.UHCReloaded.borders.shapes.MapShapeDescriptor; +import eu.carrade.amaury.UHCReloaded.borders.shapes.SquaredMapShape; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Material; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + + +public enum MapShape +{ + CIRCULAR(new CircularMapShape(), CircularWallGenerator.class), + SQUARED(new SquaredMapShape(), SquaredWallGenerator.class); + + + private MapShapeDescriptor shape; + private Class generatorClass; + + /** + * @param generator The wall generator class associated with this shape. + */ + MapShape(MapShapeDescriptor shape, Class generator) + { + this.shape = shape; + this.generatorClass = generator; + } + + /** + * Returns a new instance of the wall generator for this shape. + * + * @return The instance. + */ + public WallGenerator getWallGeneratorInstance(Material wallBlockAir, Material wallBlockSolid) + { + try + { + Constructor constructor = generatorClass.getConstructor(Material.class, Material.class); + return (WallGenerator) constructor.newInstance(wallBlockAir, wallBlockSolid); + + } + catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) + { + PluginLogger.error("Cannot instantiate the walls generator: invalid class.", e); + return null; + } + } + + /** + * Returns the shape descriptor. + * + * @return The shape. + */ + public MapShapeDescriptor getShape() + { + return shape; + } + + /** + * Returns a shape based on his name. + * + *

Not case sensitive.

+ * + * @param name The name. + * @return The MapShape, or {@code null} if not found. + */ + public static MapShape fromString(String name) + { + try + { + return MapShape.valueOf(name.trim().toUpperCase()); + } + catch (IllegalArgumentException e) + { + return null; + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/CannotGenerateWallsException.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/CannotGenerateWallsException.java new file mode 100644 index 0000000..6dc5eae --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/CannotGenerateWallsException.java @@ -0,0 +1,42 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.exceptions; + +public class CannotGenerateWallsException extends Exception +{ + + public CannotGenerateWallsException(String message) + { + super(message); + } + +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/UnknownWallGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/UnknownWallGenerator.java new file mode 100644 index 0000000..69d11cf --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/exceptions/UnknownWallGenerator.java @@ -0,0 +1,42 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.exceptions; + +public class UnknownWallGenerator extends Exception +{ + + public UnknownWallGenerator(String message) + { + super(message); + } + +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/CircularWallGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/CircularWallGenerator.java new file mode 100644 index 0000000..dc90c51 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/CircularWallGenerator.java @@ -0,0 +1,173 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.generators; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; + + +public class CircularWallGenerator extends WallGenerator +{ + public CircularWallGenerator(Material wallBlockAir, Material wallBlockSolid) + { + super(wallBlockAir, wallBlockSolid); + } + + /** + * Builds a wall in the world. + * + * @param world The world the wall will be built in. + * @param diameter The diameter of the wall. + * @param wallHeight The height of the wall. + */ + @Override + public void build(World world, int diameter, int wallHeight) + { + // Only one quarter of the circle is explicitly set, the other parts are generated + // following the first quarter. + // The quarter chosen to be explicitly generated if the one on the South-East, + // starting at x = xSpawn+radius ; z = zSpawn and ending at x = xSpawn ; z = zSpawn+radius. + + // In each step we gets the three blocks susceptible to be the next block and we calculates the + // distance from the center to these blocks. + // The good block if the one with the closest distance to the radius. + + Integer radius = (int) Math.floor(diameter / 2); + + Integer xSpawn = world.getSpawnLocation().getBlockX(); + Integer ySpawn = world.getSpawnLocation().getBlockY(); + Integer zSpawn = world.getSpawnLocation().getBlockZ(); + + // First block. + Block currentBlock = world.getBlockAt((int) (xSpawn + radius), ySpawn, zSpawn); + + Block candidate1; + Block candidate2; + Block candidate3; + + // Infinite loop broken when the generation is done. + while (true) + { + + // 1) the current point, the symmetries and the opposite point are built. + this.buildWallPoint(world, currentBlock.getX(), currentBlock.getZ(), wallHeight, diameter); + + + // 2) the two candidates are found, except if the build is finished. + if (currentBlock.getX() == xSpawn) + { + // END + break; + } + + candidate1 = world.getBlockAt(currentBlock.getX() - 1, ySpawn, currentBlock.getZ()); + candidate2 = world.getBlockAt(currentBlock.getX() - 1, ySpawn, currentBlock.getZ() + 1); + candidate3 = world.getBlockAt(currentBlock.getX(), ySpawn, currentBlock.getZ() + 1); + + + // 3) The good block is selected + Double distanceCandidate1ToRef = Math.abs((candidate1.getLocation().distance(world.getSpawnLocation()) - radius)); + Double distanceCandidate2ToRef = Math.abs((candidate2.getLocation().distance(world.getSpawnLocation()) - radius)); + Double distanceCandidate3ToRef = Math.abs((candidate3.getLocation().distance(world.getSpawnLocation()) - radius)); + + if (distanceCandidate1ToRef < distanceCandidate2ToRef && distanceCandidate1ToRef < distanceCandidate3ToRef) + { // The first is better + currentBlock = candidate1; + } + else if (distanceCandidate2ToRef < distanceCandidate1ToRef && distanceCandidate2ToRef < distanceCandidate3ToRef) + { // The second is better + currentBlock = candidate2; + } + else + { + currentBlock = candidate3; + } + } + } + + + /** + * Builds 4 "towers" of the wall, from y=0 to y=wallHeight, at the given coordinates, and + * the symmetric points. + * + * @param world + * @param x + * @param z + * @param wallHeight + * @param diameter + */ + private void buildWallPoint(World world, int x, int z, int wallHeight, int diameter) + { + + WallPosition positionOriginal; + WallPosition positionSymmetricX; + WallPosition positionSymmetricZ; + WallPosition positionOpposite; + + Integer xSpawn = world.getSpawnLocation().getBlockX(); + Integer zSpawn = world.getSpawnLocation().getBlockZ(); + + // We generates first the bedrock at y=0 + world.getBlockAt(x, 0, z).setType(Material.BEDROCK); + world.getBlockAt(x - 2 * (x - xSpawn), 0, z).setType(Material.BEDROCK); + world.getBlockAt(x, 0, z + 2 * (zSpawn - z)).setType(Material.BEDROCK); + world.getBlockAt(x - 2 * (x - xSpawn), 0, z + 2 * (zSpawn - z)).setType(Material.BEDROCK); + + + // Following the way the wall is generated, the position of the original + // "tower" can only be « SOUTH » or « EAST ». + if (z > Math.floor(diameter / 2)) + { + positionOriginal = WallPosition.SOUTH; + positionSymmetricX = WallPosition.SOUTH; + positionSymmetricZ = WallPosition.NORTH; + positionOpposite = WallPosition.NORTH; + } + else + { + positionOriginal = WallPosition.EAST; + positionSymmetricX = WallPosition.WEST; + positionSymmetricZ = WallPosition.EAST; + positionOpposite = WallPosition.WEST; + } + + // The 4 towers are built. + for (int y = 1; y <= wallHeight; y++) + { + setBlock(world.getBlockAt(x, y, z), positionOriginal); + setBlock(world.getBlockAt(x - 2 * (x - xSpawn), y, z), positionSymmetricX); + setBlock(world.getBlockAt(x, y, z + 2 * (zSpawn - z)), positionSymmetricZ); + setBlock(world.getBlockAt(x - 2 * (x - xSpawn), y, z + 2 * (zSpawn - z)), positionOpposite); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/SquaredWallGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/SquaredWallGenerator.java new file mode 100644 index 0000000..ba8ae31 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/SquaredWallGenerator.java @@ -0,0 +1,94 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.generators; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; + + +public class SquaredWallGenerator extends WallGenerator +{ + public SquaredWallGenerator(Material wallBlockAir, Material wallBlockSolid) + { + super(wallBlockAir, wallBlockSolid); + } + + /** + * Builds a wall in the world. + * + * @param world The world the wall will be built in. + * @param diameter The diameter of the wall. + * @param wallHeight The height of the wall. + */ + @Override + public void build(World world, int diameter, int wallHeight) + { + Integer halfDiameter = (int) Math.floor(diameter / 2); + + Location spawn = world.getSpawnLocation(); + Integer limitXInf = spawn.add(-halfDiameter, 0, 0).getBlockX(); + + spawn = world.getSpawnLocation(); + Integer limitXSup = spawn.add(halfDiameter, 0, 0).getBlockX(); + + spawn = world.getSpawnLocation(); + Integer limitZInf = spawn.add(0, 0, -halfDiameter).getBlockZ(); + + spawn = world.getSpawnLocation(); + Integer limitZSup = spawn.add(0, 0, halfDiameter).getBlockZ(); + + for (Integer x = limitXInf; x <= limitXSup; x++) + { + world.getBlockAt(x, 1, limitZInf).setType(Material.BEDROCK); + world.getBlockAt(x, 1, limitZSup).setType(Material.BEDROCK); + + for (Integer y = 2; y <= wallHeight; y++) + { + setBlock(world.getBlockAt(x, y, limitZInf), WallPosition.NORTH); + setBlock(world.getBlockAt(x, y, limitZSup), WallPosition.SOUTH); + } + } + + for (Integer z = limitZInf + 1; z <= limitZSup - 1; z++) + { + world.getBlockAt(limitXInf, 1, z).setType(Material.BEDROCK); + world.getBlockAt(limitXSup, 1, z).setType(Material.BEDROCK); + + for (Integer y = 2; y <= wallHeight; y++) + { + setBlock(world.getBlockAt(limitXInf, y, z), WallPosition.WEST); + setBlock(world.getBlockAt(limitXSup, y, z), WallPosition.EAST); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallGenerator.java new file mode 100644 index 0000000..f3bf52b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallGenerator.java @@ -0,0 +1,190 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.borders.generators; + +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; + + +public abstract class WallGenerator +{ + + private Material wallBlockAir = null; + private Material wallBlockSolid = null; + + private int blocksSet = 0; + + public WallGenerator(Material wallBlockAir, Material wallBlockSolid) + { + this.wallBlockAir = wallBlockAir; + this.wallBlockSolid = wallBlockSolid; + } + + + /** + * Builds a wall in the world. + * + * @param world The world the wall will be built in. + * @param diameter The diameter of the wall. + * @param wallHeight The height of the wall. + */ + public abstract void build(World world, int diameter, int wallHeight); + + + /** + * Sets a block according to his environment. + * If the block replaces a "air/tree" block, or if it is next to a transparent block, it needs to be a + * "wall.block.replaceAir" block. + * In all other cases, it needs to be a "wall.block.replaceSolid" one. + * + * @param block The block to set. + * @param position The position of the current wall in the world + */ + protected void setBlock(Block block, WallPosition position) + { + // The block is a transparent block or a tree + if (isBlockTransparentOrNatural(block.getType())) + { + block.setType(wallBlockAir); + } + // We set the block according to the block near it inside the border. + else + { + Material innerMaterial = getInnerBlock(block, position).getType(); + if (isBlockTransparentOrNatural(innerMaterial)) + { + block.setType(wallBlockAir); + } + else + { + block.setType(wallBlockSolid); + } + } + + this.blocksSet++; + } + + /** + * Checks if a block is transparent or is part of a tree. + * Used to generate the wall. + * + * @return boolean True if the block is transparent, or part of a tree/a giant mushroom/a + * generated structure/etc. + */ + protected Boolean isBlockTransparentOrNatural(Material blockType) + { + if (blockType.isTransparent()) + { + return true; + } + + switch (blockType) + { + case GLASS: // The glass isn't a transparent block for the `isTransparent` method. + case STAINED_GLASS: + case THIN_GLASS: + case STAINED_GLASS_PANE: + case LEAVES: + case LEAVES_2: + case LOG: + case LOG_2: + case CHEST: // Avoid a cube of the solid block where there where a chest. + case TRAPPED_CHEST: + case ENDER_CHEST: + case WATER: + case STATIONARY_WATER: + case BED_BLOCK: + case PISTON_STICKY_BASE: // Same idea (in jungle temples). + case PISTON_BASE: + case BOOKSHELF: // Same idea (in villages & fortresses). + case MOB_SPAWNER: // Same idea (in dungeons). + case SIGN_POST: + case WALL_SIGN: + case ICE: // Same idea (in cold biomes). + case PACKED_ICE: + case CACTUS: // Same idea (in deserts) + case FENCE: + case FENCE_GATE: + case IRON_FENCE: + case NETHER_FENCE: + case PUMPKIN: + case MELON_BLOCK: // Same idea (in jungles) + case GLOWSTONE: // Same idea (in the Nether - why not?) + case JACK_O_LANTERN: + case HUGE_MUSHROOM_1: // Same idea (in dark forests). + case HUGE_MUSHROOM_2: + case CAKE_BLOCK: // It may be a lie, but hey, why not. + case BEACON: + case COBBLE_WALL: + case ANVIL: + return true; + default: + return false; + } + } + + /** + * Gets the block left to the given block inside the border. + * + * @param block The reference block. + * @param position The position of the wall currently build. + */ + protected Block getInnerBlock(Block block, WallPosition position) + { + // Just for readability. + World world = block.getWorld(); + Integer x = block.getX(); + Integer y = block.getY(); + Integer z = block.getZ(); + + switch (position) + { + case EAST: + return world.getBlockAt(x - 1, y, z); + case NORTH: + return world.getBlockAt(x, y, z + 1); + case SOUTH: + return world.getBlockAt(x, y, z - 1); + case WEST: + return world.getBlockAt(x + 1, y, z); + default: // wait what? + return null; + } + } + + public int getBlocksSet() + { + return blocksSet; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallPosition.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallPosition.java new file mode 100644 index 0000000..1d6cab6 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/generators/WallPosition.java @@ -0,0 +1,49 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.borders.generators; + +/** + * Used to determine in witch wall we are, to get the "inner" block. + * + * North: small Z + * South: big Z + * East: big X + * West: small X + */ +public enum WallPosition +{ + NORTH, + SOUTH, + EAST, + WEST +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/CircularMapShape.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/CircularMapShape.java new file mode 100644 index 0000000..62fa1cd --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/CircularMapShape.java @@ -0,0 +1,87 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.shapes; + +import org.bukkit.Location; +import org.bukkit.World; + + +public class CircularMapShape implements MapShapeDescriptor +{ + /** + * Returns true if the given location is inside the map. + * + * @param location The location to check. + * @param diameter The diameter of the map. + * @param center The center of the map. + * + * @return {@code true} if the given location is inside the map. + */ + @Override + public boolean isInsideBorder(final Location location, final Double diameter, final Location center) + { + Location centerRef = center.clone(); + centerRef.setY(location.getY()); + + return (location.distance(centerRef) <= Math.floor(diameter / 2)); + } + + /** + * Returns the distance between the given location and the border with this diameter. + * + * @param location The distance will be calculated between this location and the closest point of the border. + * @param diameter The diameter of the border. + * @param center The center of the border. + * + * @return The distance between the given {@code location} and the closest point of the border.
+ * {@code -1} if the location is inside the border. + */ + @Override + public double getDistanceToBorder(final Location location, final Double diameter, final Location center) + { + // The nether/end are not limited. + if (!location.getWorld().getEnvironment().equals(World.Environment.NORMAL)) + { + return -1; + } + + if (isInsideBorder(location, diameter, center)) + { + return -1; + } + + Location centerRef = center.clone(); + centerRef.setY(location.getY()); + + return (location.distance(centerRef) - Math.floor(diameter / 2)); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/MapShapeDescriptor.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/MapShapeDescriptor.java new file mode 100644 index 0000000..c2590c5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/MapShapeDescriptor.java @@ -0,0 +1,64 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.shapes; + +import org.bukkit.Location; + + +/** + * Represents a shape of the map. + */ +public interface MapShapeDescriptor +{ + /** + * Returns true if the given location is inside the map. + * + * @param location The location to check. + * @param diameter The diameter of the map. + * @param center The center of the map. + * + * @return {@code true} if the given location is inside the map. + */ + boolean isInsideBorder(final Location location, final Double diameter, final Location center); + + /** + * Returns the distance between the given location and the border with this diameter. + * + * @param location The distance will be calculated between this location and the closest point of the border. + * @param diameter The diameter of the border. + * @param center The center of the border. + * + * @return The distance between the given {@code location} and the closest point of the border.
+ * {@code -1} if the location is inside the border. + */ + double getDistanceToBorder(final Location location, final Double diameter, final Location center); +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/SquaredMapShape.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/SquaredMapShape.java new file mode 100644 index 0000000..b2d282d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/shapes/SquaredMapShape.java @@ -0,0 +1,134 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.shapes; + +import org.bukkit.Location; +import org.bukkit.World; + + +public class SquaredMapShape implements MapShapeDescriptor +{ + /** + * Returns true if the given location is inside the map. + * + * @param location The location to check. + * @param diameter The diameter of the map. + * @param center The center of the map. + * + * @return {@code true} if the given location is inside the map. + */ + @Override + public boolean isInsideBorder(final Location location, final Double diameter, final Location center) + { + Integer halfMapSize = (int) Math.floor(diameter / 2); + Integer x = location.getBlockX(); + Integer z = location.getBlockZ(); + + Integer limitXInf = center.clone().add(-halfMapSize, 0, 0).getBlockX(); + Integer limitXSup = center.clone().add(halfMapSize, 0, 0).getBlockX(); + Integer limitZInf = center.clone().add(0, 0, -halfMapSize).getBlockZ(); + Integer limitZSup = center.clone().add(0, 0, halfMapSize).getBlockZ(); + + return !(x < limitXInf || x > limitXSup || z < limitZInf || z > limitZSup); + } + + /** + * Returns the distance between the given location and the border with this diameter. + * + * @param location The distance will be calculated between this location and the closest point of the border. + * @param diameter The diameter of the border. + * @param center The center of the border. + * + * @return The distance between the given {@code location} and the closest point of the border.
+ * {@code -1} if the location is inside the border. + */ + @Override + public double getDistanceToBorder(final Location location, final Double diameter, final Location center) + { + // The nether/end are not limited. + if (!location.getWorld().getEnvironment().equals(World.Environment.NORMAL)) + { + return -1; + } + + if (isInsideBorder(location, diameter, center)) + { + return -1; + } + + Integer halfMapSize = (int) Math.floor(diameter / 2); + Integer x = location.getBlockX(); + Integer z = location.getBlockZ(); + + Integer limitXInf = center.clone().add(-halfMapSize, 0, 0).getBlockX(); + Integer limitXSup = center.clone().add(halfMapSize, 0, 0).getBlockX(); + Integer limitZInf = center.clone().add(0, 0, -halfMapSize).getBlockZ(); + Integer limitZSup = center.clone().add(0, 0, halfMapSize).getBlockZ(); + + if (x > limitXSup && z < limitZSup && z > limitZInf) // East of the border + { + return Math.abs(x - limitXSup); + } + else if (x < limitXInf && z < limitZSup && z > limitZInf) // West of the border + { + return Math.abs(x - limitXInf); + } + else if (z > limitZSup && x < limitXSup && x > limitXInf) // South of the border + { + return Math.abs(z - limitZSup); + } + else if (z < limitZInf && x < limitXSup && x > limitXInf) // North of the border + { + return Math.abs(z - limitZInf); + } + else if (x > limitXSup && z < limitZInf) // North-East + { + return (int) location.distance(new Location(location.getWorld(), limitXSup, location.getBlockY(), limitZInf)); + } + else if (x > limitXSup && z > limitZSup) // South-East + { + return (int) location.distance(new Location(location.getWorld(), limitXSup, location.getBlockY(), limitZSup)); + } + else if (x < limitXInf && z > limitZSup) // South-West + { + return (int) location.distance(new Location(location.getWorld(), limitXInf, location.getBlockY(), limitZSup)); + } + else if (x < limitXInf && z < limitZInf) // North-West + { + return (int) location.distance(new Location(location.getWorld(), limitXInf, location.getBlockY(), limitZInf)); + } + else + { + return -1; // Should never happen. + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/BrettflanWorldBorder.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/BrettflanWorldBorder.java new file mode 100644 index 0000000..0412f2b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/BrettflanWorldBorder.java @@ -0,0 +1,229 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.worldborders; + +import com.wimbli.WorldBorder.BorderData; +import com.wimbli.WorldBorder.Config; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import fr.zcraft.zlib.tools.runners.RunTask; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.scheduler.BukkitTask; + + +/** + * Represents a Brettflan world border, from the WorldBorder Bukkit plugin. + * + *

These methods are not supported as the border cannot be bypassed and does not have + * warnings:

+ *
    + *
  • {@link #setDamageBuffer(double)};
  • + *
  • {@link #setDamageAmount(double)};
  • + *
  • {@link #setWarningDistance(int)};
  • + *
  • {@link #setWarningTime(int)}.
  • + *
+ */ +public class BrettflanWorldBorder extends WorldBorder +{ + private World world; + private BorderData border; + + private Double diameter = 0d; + + private BukkitTask slowReductionTask = null; + + + public BrettflanWorldBorder(World world) + { + this.world = world; + + com.wimbli.WorldBorder.WorldBorder wb = UHCReloaded.get().getWorldBorderIntegration().getWorldBorder(); + if (wb != null) + { + border = wb.getWorldBorder(world.getName()); + + if (border == null) + { + border = new BorderData(world.getSpawnLocation().getX(), world.getSpawnLocation().getZ(), 3000000); + Config.setBorder(world.getName(), border); + } + } + } + + @Override + public void init() + { + Config.setPortalRedirection(true); + } + + @Override + public World getWorld() + { + return world; + } + + @Override + public double getDiameter() + { + // If squared, the size is not changed + if (!border.getShape()) + return diameter; + + + Double realDiameter = (double) (border.getRadiusX() * 2); + + // Returns the stored diameter, except if it was changed + // manually with /wb (see #setDiameterInternal(Double) for + // details). + if (realDiameter - diameter >= 8) + diameter = realDiameter; + + return diameter; + } + + @Override + public void setDiameter(double diameter) + { + setDiameterInternal(diameter); + + if (slowReductionTask != null) + { + slowReductionTask.cancel(); + slowReductionTask = null; + } + } + + @Override + public void setDiameter(final double diameter, final long time) + { + // The behavior of the vanilla reduction is emulated. + final double currentDiameter = getDiameter(); + + final long ticksPerBlockRemoved = (int) Math.rint(time / (currentDiameter - diameter)) * 20l; + final long movement = (diameter >= currentDiameter) ? 1 : -1; + + if (slowReductionTask != null) + { + slowReductionTask.cancel(); + slowReductionTask = null; + } + + slowReductionTask = RunTask.timer(new Runnable() { + @Override + public void run() + { + Double newDiameter = getDiameter() + movement; + + // If the final size is achieved, we set the exact requested size and we stop here. + // Calling setDiameter cancels this task. + if ((movement < 0 && newDiameter <= diameter) || (movement > 0 && newDiameter >= diameter)) + { + setDiameter(diameter); + } + else + { + setDiameterInternal(newDiameter); + } + } + }, ticksPerBlockRemoved, ticksPerBlockRemoved); + } + + private void setDiameterInternal(double diameter) + { + this.diameter = diameter; + + // If the wall is circular, the diameter used to check must be bigger to avoid false positives + // if a player is in an angle of the circular wall. The original diameter set is stored and + // returned by the getDiameter value (except if the diameter was changed using /wb), for nicer + // display (avoids rounding errors). + // “+3” ? Experimental. + int offset = (getShape() == MapShape.CIRCULAR) ? 3 : 0; + + border.setRadius((int) Math.floor((diameter + offset) / 2)); + } + + @Override + public Location getCenter() + { + return new Location(world, border.getX(), 0, border.getZ()); + } + + @Override + public void setCenter(double x, double z) + { + border.setX(x); + border.setZ(z); + } + + @Override + public void setCenter(Location center) + { + setCenter(center.getX(), center.getZ()); + } + + @Override + public double getDamageBuffer() { return 0; } + + @Override + public void setDamageBuffer(double distance) {} + + @Override + public double getDamageAmount() { return 0; } + + @Override + public void setDamageAmount(double damageAmount) {} + + @Override + public int getWarningTime() { return 0; } + + @Override + public void setWarningTime(int seconds) {} + + @Override + public int getWarningDistance() { return 0; } + + @Override + public void setWarningDistance(int blocks) {} + + @Override + public MapShape getShape() + { + return border.getShape() ? MapShape.CIRCULAR : MapShape.SQUARED; + } + + @Override + public void setShape(MapShape shape) + { + border.setShape(shape == MapShape.CIRCULAR); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/FakeWorldBorder.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/FakeWorldBorder.java new file mode 100644 index 0000000..a93e212 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/FakeWorldBorder.java @@ -0,0 +1,136 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.worldborders; + +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import org.bukkit.Location; +import org.bukkit.World; + + +/** + * A fake world border, it does nothing. + * + *

Used when a circular world border is requested without the WorldBorder plugin.

+ */ +public class FakeWorldBorder extends WorldBorder +{ + private final World world; + + private Location center; + private Double diameter; + private MapShape shape; + + public FakeWorldBorder(World world) + { + this.world = world; + + init(); + } + + @Override + public World getWorld() + { + return world; + } + + @Override + public double getDiameter() + { + return diameter; + } + + @Override + public void setDiameter(double diameter) + { + this.diameter = diameter; + } + + @Override + public void setDiameter(double diameter, long time) + { + this.diameter = diameter; + } + + @Override + public Location getCenter() + { + return center; + } + + @Override + public void setCenter(double x, double z) + { + this.center = new Location(world, x, 0, z); + } + + @Override + public void setCenter(Location center) + { + setCenter(center.getX(), center.getZ()); + } + + @Override + public double getDamageBuffer() { return 0; } + + @Override + public void setDamageBuffer(double distance) {} + + @Override + public double getDamageAmount() { return 0; } + + @Override + public void setDamageAmount(double damageAmount) {} + + @Override + public int getWarningTime() { return 0; } + + @Override + public void setWarningTime(int seconds) {} + + @Override + public int getWarningDistance() { return 0; } + + @Override + public void setWarningDistance(int blocks) {} + + @Override + public MapShape getShape() + { + return shape; + } + + @Override + public void setShape(MapShape shape) + { + this.shape = shape; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/VanillaWorldBorder.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/VanillaWorldBorder.java new file mode 100644 index 0000000..5ca69e4 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/VanillaWorldBorder.java @@ -0,0 +1,166 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.worldborders; + +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import org.bukkit.Location; +import org.bukkit.World; + + +/** + * Represents a vanilla world border. + * + *

This border is always squared, so {@link #setShape(MapShape)} does nothing and {@link + * #getShape()} always returns {@link MapShape#SQUARED}.

+ */ +public class VanillaWorldBorder extends WorldBorder +{ + private final World world; + private final org.bukkit.WorldBorder border; + + public VanillaWorldBorder(World world) + { + this.world = world; + this.border = world.getWorldBorder(); + } + + @Override + public void init() + { + if (UHConfig.MAP.BORDER.isDefined()) + { + setDamageBuffer(UHConfig.MAP.BORDER.DAMAGES_BUFFER.get()); + setDamageAmount(UHConfig.MAP.BORDER.DAMAGES_AMOUNT.get()); + setWarningDistance(UHConfig.MAP.BORDER.WARNING_DISTANCE.get()); + } + } + + @Override + public World getWorld() + { + return world; + } + + @Override + public double getDiameter() + { + return border.getSize(); + } + + @Override + public void setDiameter(double diameter) + { + border.setSize(diameter); + } + + @Override + public void setDiameter(double diameter, long time) + { + border.setSize(diameter, time); + } + + @Override + public Location getCenter() + { + return border.getCenter(); + } + + @Override + public void setCenter(double x, double z) + { + border.setCenter(x, z); + } + + @Override + public void setCenter(Location center) + { + border.setCenter(center); + } + + @Override + public double getDamageBuffer() + { + return border.getDamageBuffer(); + } + + @Override + public void setDamageBuffer(double distance) + { + border.setDamageBuffer(distance); + } + + @Override + public double getDamageAmount() + { + return border.getDamageAmount(); + } + + @Override + public void setDamageAmount(double damageAmount) + { + border.setDamageAmount(damageAmount); + } + + @Override + public int getWarningTime() + { + return border.getWarningTime(); + } + + @Override + public void setWarningTime(int seconds) + { + border.setWarningTime(seconds); + } + + @Override + public int getWarningDistance() + { + return border.getWarningDistance(); + } + + @Override + public void setWarningDistance(int blocks) + { + border.setWarningDistance(blocks); + } + + @Override + public MapShape getShape() + { + return MapShape.SQUARED; + } + + @Override + public void setShape(MapShape shape) {} +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/WorldBorder.java b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/WorldBorder.java new file mode 100644 index 0000000..3284b79 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/borders/worldborders/WorldBorder.java @@ -0,0 +1,184 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.borders.worldborders; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import org.bukkit.Location; +import org.bukkit.World; + + +/** + * An abstraction layer to manipulate world borders, typically the vanilla world border or + * the Brettflan one. + */ +public abstract class WorldBorder +{ + /** + * Initializes the world border configuration, if needed. + * + * This method does not initializes the shape, size, etc. + */ + public void init() {} + + /** + * @return The world bordered by this world border. + */ + public abstract World getWorld(); + + /** + * @return The diameter of the border. + */ + public abstract double getDiameter(); + + /** + * @param diameter The new diameter of the border. + */ + public abstract void setDiameter(double diameter); + + /** + * @param diameter The new diameter of the border. + * @param time The ticks used to change the size from the old size to the new one. + */ + public abstract void setDiameter(double diameter, long time); + + /** + * @return The center of the border. + */ + public abstract Location getCenter(); + + /** + * Sets the center of the border. + * + * @param x The x coordinate of the new center. + * @param z The z coordinate of the new center. + */ + public abstract void setCenter(double x, double z); + + /** + * @param center The new center of the border. + */ + public abstract void setCenter(Location center); + + /** + * @return the amount of blocks a player may safely be outside the border before taking damage. + */ + public abstract double getDamageBuffer(); + + /** + * @param distance the amount of blocks a player may safely be outside the border before taking + * damage. + */ + public abstract void setDamageBuffer(double distance); + + /** + * @return the amount of damage a player takes when outside the border plus the border buffer. + */ + public abstract double getDamageAmount(); + + /** + * @param damageAmount the amount of damage a player takes when outside the border plus the + * border buffer. + */ + public abstract void setDamageAmount(double damageAmount); + + /** + * @return the warning time that causes the screen to be tinted red when a contracting border + * will reach the player within the specified time, if applicable. + */ + public abstract int getWarningTime(); + + /** + * @param seconds the warning time that causes the screen to be tinted red when a contracting + * border will reach the player within the specified time. + */ + public abstract void setWarningTime(int seconds); + + /** + * @return the warning distance that causes the screen to be tinted red when the player is + * within the specified number of blocks from the border. + */ + public abstract int getWarningDistance(); + + /** + * @param blocks the warning distance that causes the screen to be tinted red when the player is + * within the specified number of blocks from the border. + */ + public abstract void setWarningDistance(int blocks); + + /** + * @return The current border shape. + */ + public abstract MapShape getShape(); + + /** + * @param shape the new border shape. + */ + public abstract void setShape(MapShape shape); + + + /** + * Returns a new instance of a WorldBorder proxy using the requested types. + * + * @param motor The border motor; can be "vanilla" or "brettflan" (from config). + * @param shape The border shape. + * + * @return An instance of a WorldBorder proxy. + */ + public static WorldBorder getInstance(World world, String motor, MapShape shape) + { + // For circular shapes, the vanilla motor cannot be used. + // Without the WorldBorder plugin, a fake world border is used (i.e., no border control). + if (shape == MapShape.CIRCULAR) + { + if (UHCReloaded.get().getWorldBorderIntegration().isWBIntegrationEnabled()) + { + return new BrettflanWorldBorder(world); + } + else + { + return new FakeWorldBorder(world); + } + } + else + { + if (motor.equalsIgnoreCase("vanilla") || !UHCReloaded.get().getWorldBorderIntegration().isWBIntegrationEnabled()) + { + return new VanillaWorldBorder(world); + } + else + { + return new BrettflanWorldBorder(world); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/UHCommandExecutor.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/UHCommandExecutor.java new file mode 100644 index 0000000..ec1fe52 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/UHCommandExecutor.java @@ -0,0 +1,63 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.GlobalMessageCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.JoinCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.LeaveCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.TeamMessageCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.TeamsCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.ToggleChatCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.UHRootCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommandExecutor; + + +public class UHCommandExecutor extends AbstractCommandExecutor +{ + + public UHCommandExecutor(UHCReloaded p) + { + super(p); + + + registerCommand(new UHRootCommand(p)); // /uh + + registerCommand(new JoinCommand(p)); // /join + registerCommand(new LeaveCommand(p)); // /leave + registerCommand(new TeamsCommand(p)); // /teams + + registerCommand(new TeamMessageCommand(p)); // /t + registerCommand(new GlobalMessageCommand(p)); // /g + registerCommand(new ToggleChatCommand(p)); // /togglechat + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java new file mode 100644 index 0000000..484914b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java @@ -0,0 +1,117 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +/** + * This command, /g , is used to send a global message while being in + * the locked team-chat. + */ +@Command (name = "g", noPermission = true) +public class GlobalMessageCommand extends AbstractCommand +{ + private UHCReloaded p; + + public GlobalMessageCommand(UHCReloaded p) + { + this.p = p; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + + // /t + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String message = ""; + for (String arg : args) + { + message += arg + " "; + } + + p.getTeamChatManager().sendGlobalMessage((Player) sender, message); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + + @Override + public List help(CommandSender sender) + { + /// Usage of the /g and /t commands + return Collections.singletonList(I.t("{ce}Usage: /{0} ", "g")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return null; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/JoinCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/JoinCommand.java new file mode 100644 index 0000000..59d55f6 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/JoinCommand.java @@ -0,0 +1,68 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamJoinCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + + +// The permissions are too complex, we need to manage them manually. +@Command (name = "join", noPermission = true, inheritPermission = false) +public class JoinCommand extends UHTeamJoinCommand +{ + private UHCReloaded p; + + public JoinCommand(UHCReloaded plugin) + { + super(plugin); + p = plugin; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0 && sender instanceof Player + && sender.hasPermission("uh.player.join.self")) + { + p.getTeamManager().displayTeamChooserChatGUI((Player) sender); + } + + else + { + super.run(sender, args); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/LeaveCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/LeaveCommand.java new file mode 100644 index 0000000..92d6f8e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/LeaveCommand.java @@ -0,0 +1,47 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamLeaveCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; + + +// The permissions are too complex, we need to manage them manually. +@Command (name = "leave", noPermission = true, inheritPermission = false) +public class LeaveCommand extends UHTeamLeaveCommand +{ + public LeaveCommand(UHCReloaded plugin) + { + super(plugin); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java new file mode 100644 index 0000000..636ed63 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java @@ -0,0 +1,116 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +/** + * This command, /t , is used to send a team-message. + */ +@Command (name = "t", noPermission = true) +public class TeamMessageCommand extends AbstractCommand +{ + private UHCReloaded p; + + public TeamMessageCommand(UHCReloaded p) + { + this.p = p; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + + // /t + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String message = ""; + for (String arg : args) + { + message += arg + " "; + } + + p.getTeamChatManager().sendTeamMessage((Player) sender, message); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + + @Override + public List help(CommandSender sender) + { + /// Usage of the /g and /t commands + return Collections.singletonList(I.t("{ce}Usage: /{0} ", "t")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return null; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamsCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamsCommand.java new file mode 100644 index 0000000..75d5b14 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamsCommand.java @@ -0,0 +1,46 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamGUICommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; + + +@Command (name = "teams", noPermission = true, inheritPermission = false) +public class TeamsCommand extends UHTeamGUICommand +{ + public TeamsCommand(UHCReloaded plugin) + { + super(plugin); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java new file mode 100644 index 0000000..38aaf62 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java @@ -0,0 +1,134 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + + +/** + * This command, /togglechat, is used to toggle the chat between the global chat and + * the team chat. + */ +@Command (name = "togglechat", noPermission = true) +public class ToggleChatCommand extends AbstractCommand +{ + private UHCReloaded p; + + public ToggleChatCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + + // /togglechat + if (args.length == 0) + { + if (p.getTeamChatManager().toggleChatForPlayer((Player) sender)) + { + sender.sendMessage(I.t("{cs}You are now chatting with your team only.")); + } + else + { + sender.sendMessage(I.t("{cs}You are now chatting with everyone.")); + } + } + + // /togglechat + else + { + String teamName = UHUtils.getStringFromCommandArguments(args, 0); + UHTeam team = p.getTeamManager().getTeam(teamName); + + if (team != null) + { + if (p.getTeamChatManager().toggleChatForPlayer((Player) sender, team)) + { + sender.sendMessage(I.t("{cs}You are now chatting with the team {0}{cs}.", team.getDisplayName())); + } + } + else + { + sender.sendMessage(I.t("{ce}This team does not exists.")); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (sender instanceof Player && sender.hasPermission("uh.teamchat.others")) + { + ArrayList teamNames = new ArrayList<>(); + + for (UHTeam team : p.getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return null; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java new file mode 100644 index 0000000..754bd26 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/UHRootCommand.java @@ -0,0 +1,128 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHAboutCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHBorderCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHFeedAllCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHFeedCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHFinishCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHFreezeCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHGenerateWallsCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHHealAllCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHHealCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHInfosCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHKillCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHLoadPlayersCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHResurrectCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHRulesCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHShiftCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHSpawnsCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHSpectatorsCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHStartCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPBackCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTPSpawnCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTeamCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.UHTimersCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import org.bukkit.command.CommandSender; + +import java.util.List; + + +@Command (name = "uh") +public class UHRootCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHRootCommand(UHCReloaded plugin) + { + p = plugin; + + // Game + registerSubCommand(new UHStartCommand(p)); + registerSubCommand(new UHShiftCommand(p)); + registerSubCommand(new UHSpawnsCommand(p)); + registerSubCommand(new UHTeamCommand(p)); + registerSubCommand(new UHBorderCommand(p)); + registerSubCommand(new UHSpectatorsCommand(p)); + registerSubCommand(new UHGenerateWallsCommand(p)); + + // Bugs + registerSubCommand(new UHHealCommand(p)); + registerSubCommand(new UHHealAllCommand(p)); + registerSubCommand(new UHFeedCommand(p)); + registerSubCommand(new UHFeedAllCommand(p)); + registerSubCommand(new UHKillCommand(p)); + registerSubCommand(new UHResurrectCommand(p)); + registerSubCommand(new UHTPBackCommand(p)); + registerSubCommand(new UHTPSpawnCommand(p)); + + // Misc + registerSubCommand(new UHFinishCommand(p)); + registerSubCommand(new UHFreezeCommand(p)); + registerSubCommand(new UHTimersCommand(p)); + registerSubCommand(new UHTPCommand(p)); + registerSubCommand(new UHInfosCommand(p)); + registerSubCommand(new UHRulesCommand(p)); + registerSubCommand(new UHLoadPlayersCommand()); + registerSubCommand(new UHAboutCommand(p)); + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return null; + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java new file mode 100644 index 0000000..896d66b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java @@ -0,0 +1,55 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.categories; + +import fr.zcraft.zlib.components.i18n.I; + + +public enum Category +{ + GAME(I.t("{aqua}------ Game-related commands ------")), + BUGS(I.t("{aqua}------ Bugs-related commands ------")), + MISC(I.t("{aqua}------ Miscellaneous commands ------")); + + + private String title; + + Category(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java new file mode 100644 index 0000000..5b821fc --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java @@ -0,0 +1,178 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.i18n.I18n; +import org.bukkit.command.CommandSender; + +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + + +/** + * This command prints some informations about the plugin and the translation. + * + * Usage: /uh about + */ +@Command (name = "about") +public class UHAboutCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHAboutCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + CommandUtils.displaySeparator(sender); + sender.sendMessage(I.t("{yellow}{0} - version {1}", p.getDescription().getDescription(), p.getDescription().getVersion())); + + // Authors + + String authors = ""; + List listAuthors = p.getDescription().getAuthors(); + for (String author : listAuthors) + { + if (author == listAuthors.get(0)) + { + // Nothing + } + else if (author == listAuthors.get(listAuthors.size() - 1)) + { + /// The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") + authors += " " + I.tc("authors_list", "and") + " "; + } + else + { + authors += ", "; + } + authors += author; + } + sender.sendMessage(I.t("Plugin made with love by {0}.", authors)); + + // Build number + + String build = null; + try + { + Class clazz = p.getClass(); + String className = clazz.getSimpleName() + ".class"; + String classPath = clazz.getResource(className).toString(); + if (classPath.startsWith("jar")) // Class from JAR + { + String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + + "/META-INF/MANIFEST.MF"; + Manifest manifest = new Manifest(new URL(manifestPath).openStream()); + Attributes attr = manifest.getMainAttributes(); + + build = attr.getValue("Git-Commit"); + } + } + catch (IOException e) + { + // Build not available. + } + + if (build != null) + { + sender.sendMessage(I.t("Build number: {0}.", build)); + } + else + { + sender.sendMessage(I.t("Build number not available.")); + } + + // Translation + + sender.sendMessage(I.t("{aqua}------ Translations ------")); + sender.sendMessage(I.t("Current language: {0} (translated by {1}).", I18n.getPrimaryLocale(), I18n.getTranslationTeam(I18n.getPrimaryLocale()))); + sender.sendMessage(I.t("Fallback language: {0} (translated by {1}).", I18n.getFallbackLocale(), I18n.getTranslationTeam(I18n.getFallbackLocale()))); + sender.sendMessage(I.t("{aqua}------ License ------")); + sender.sendMessage(I.t("Published under the CeCILL-B License.")); + + CommandUtils.displaySeparator(sender); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh about {ci}: informations about the plugin and the translation.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java new file mode 100644 index 0000000..f83ab73 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java @@ -0,0 +1,97 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.border.UHBorderCheckCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.border.UHBorderGetCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.border.UHBorderSetCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.border.UHBorderWarningCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + + +/** + * This command manages borders (gets current, checks if players are out, sets a new size, warns players + * about the future size). + * + * Usage: /uh border (doc) + * Usage: /uh border + */ +@Command (name = "border") +public class UHBorderCommand extends AbstractCommand +{ + public UHBorderCommand(UHCReloaded p) + { + registerSubCommand(new UHBorderGetCommand(p)); + registerSubCommand(new UHBorderSetCommand(p)); + registerSubCommand(new UHBorderWarningCommand(p)); + registerSubCommand(new UHBorderCheckCommand(p)); + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return Collections.singletonList(I.t("{aqua}------ Border commands ------")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh border {ci}: manages borders. Execute /uh border for details.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java new file mode 100644 index 0000000..bb33b13 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java @@ -0,0 +1,124 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; +/** + * This command feeds all player. + * + * Usage: /uh feed <player> [foodLevel=20] [saturation=20] + */ +@Command (name = "feedall") +public class UHFeedAllCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHFeedAllCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + + int foodLevel = 20; + float saturation = 20f; + + if (args.length > 0) // /uh feedall + { + try + { + foodLevel = Integer.valueOf(args[0]); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Food points and saturation must be numbers (floats for the saturation)!")); + return; + } + + if (args.length > 1) // /uh feedall + { + try + { + // The saturation value cannot be more than the food level. + saturation = Math.min(foodLevel, Float.valueOf(args[1])); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Food points and saturation must be numbers (floats for the saturation)!")); + return; + } + } + } + + for (Player player : p.getServer().getOnlinePlayers()) + { + player.setFoodLevel(foodLevel); + player.setSaturation(saturation); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players.")); + } + + @Override + public String getCategory() + { + return Category.BUGS.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java new file mode 100644 index 0000000..c3e504d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java @@ -0,0 +1,133 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +/** + * This command feeds a player. + * + * Usage: /uh feed <player> [foodLevel=20] [saturation=20] + */ +@Command (name = "feed") +public class UHFeedCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHFeedCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length < 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + Player target = p.getServer().getPlayer(args[0]); + if (target == null || !target.isOnline()) + { + sender.sendMessage(I.t("{ce}This player is offline.")); + return; + } + + int foodLevel = 20; + float saturation = 20f; + + if (args.length > 1) // /uh feed + { + try + { + foodLevel = Integer.valueOf(args[1]); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Food points and saturation must be numbers (floats for the saturation)!")); + return; + } + + if (args.length > 2) // /uh feed + { + try + { + // The saturation value cannot be more than the food level. + saturation = Math.min(foodLevel, Float.valueOf(args[2])); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Food points and saturation must be numbers (floats for the saturation)!")); + return; + } + } + } + + target.setFoodLevel(foodLevel); + target.setSaturation(saturation); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh feed [foodPoints=20] [saturation=max] {ci}: feeds a player.")); + } + + @Override + public String getCategory() + { + return Category.BUGS.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java new file mode 100644 index 0000000..a25d76b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java @@ -0,0 +1,112 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.game.UHGameManager; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +/** + * This commands broadcast the winner(s) of the game and sends some fireworks at these players. + * It fails if there is more than one team alive. + * + * Usage: /uh finish + */ +@Command (name = "finish") +public class UHFinishCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHFinishCommand(UHCReloaded plugin) + { + this.p = plugin; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + try + { + p.getGameManager().finishGame(); + + } + catch (IllegalStateException e) + { + + if (e.getMessage().equals(UHGameManager.FINISH_ERROR_NOT_STARTED)) + { + sender.sendMessage(I.t("{ce}The game is not started!")); + } + else if (e.getMessage().equals(UHGameManager.FINISH_ERROR_NOT_FINISHED)) + { + sender.sendMessage(I.t("{ce}There's not one team alive!")); + } + else + { + throw e; + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh finish {ci}: displays the name of the winner(s) and launches some fireworks.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java new file mode 100644 index 0000000..6fc04d0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java @@ -0,0 +1,200 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * This command freezes the players. + * + * Usage: /uh freeze + * - on [player]: freezes the given player, or the sender if no player was provided. + * - off [player]: unfreezes the given player (or the sender, same condition). + * - all: freezes all the alive players, the mobs and the timer. + * - none: unfreezes all the alive players (even if there where frozen before using + * /uh freeze all), the mobs and the timer. + */ +@Command (name = "freeze") +public class UHFreezeCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHFreezeCommand(UHCReloaded plugin) + { + p = plugin; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + String subCommand = args[0]; + + if (subCommand.equalsIgnoreCase("on") || subCommand.equalsIgnoreCase("off")) + { + + boolean on = subCommand.equalsIgnoreCase("on"); + + if (args.length == 1) + { // /uh freeze on: freezes the sender + if (sender instanceof Player) + { + p.getFreezer().setPlayerFreezeState((Player) sender, on); + + if (on) + { + sender.sendMessage(I.t("{cst}You where frozen by {0}.", sender.getName())); + } + else + { + sender.sendMessage(I.t("{cst}You where unfrozen by {0}.", sender.getName())); + } + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + } + else if (args.length == 2) + { // /uh freeze on : freezes . + Player player = p.getServer().getPlayer(args[1]); + if (player == null) + { + sender.sendMessage(I.t("{ce}{0} is offline!", args[1])); + } + else + { + p.getFreezer().setPlayerFreezeState(player, on); + if (on) + { + player.sendMessage(I.t("{cst}You where frozen by {0}.", sender.getName())); + sender.sendMessage(I.t("{cs}{0} is now frozen.", player.getName())); + } + else + { + player.sendMessage(I.t("{cst}You where unfrozen by {0}.", sender.getName())); + sender.sendMessage(I.t("{cs}{0} is now unfrozen.", player.getName())); + } + } + } + } + + else if (subCommand.equalsIgnoreCase("all") || subCommand.equalsIgnoreCase("none")) + { + + boolean on = subCommand.equalsIgnoreCase("all"); + + p.getFreezer().setGlobalFreezeState(on); + + if (on) + { + p.getServer().broadcastMessage(I.t("{darkaqua}The entire game is now frozen.")); + } + else + { + p.getServer().broadcastMessage(I.t("{darkaqua}The game is now unfrozen.")); + } + + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + return CommandUtils.getAutocompleteSuggestions( + args[0], Arrays.asList("on", "off", "all", "none") + ); + } + + else if (args.length == 2) + { + if (args[0].equalsIgnoreCase("off")) + { + List suggestions = new ArrayList<>(); + + for (Player player : p.getFreezer().getFrozenPlayers()) + { + suggestions.add(player.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(args[1], suggestions); + } + + else return null; + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return Arrays.asList( + I.t("{aqua}------ Freeze commands ------"), + I.t("{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a specified player."), + I.t("{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if the entire game is frozen."), + I.t("{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)."), + I.t("{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this in order to relaunch the timer.") + ); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh freeze for details.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java new file mode 100644 index 0000000..45ad57e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java @@ -0,0 +1,145 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.exceptions.CannotGenerateWallsException; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.World; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +/** + * This command generates the walls around the map. + * + * Usage: /uh generatewalls + */ +@Command (name = "generatewalls") +public class UHGenerateWallsCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHGenerateWallsCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + sender.sendMessage(I.t("{cst}Generating the walls...")); + + World world = null; + + if (sender instanceof Player) + { + world = ((Player) sender).getWorld(); + } + else if (sender instanceof BlockCommandSender) + { + world = ((BlockCommandSender) sender).getBlock().getWorld(); + } + else + { + world = p.getServer().getWorlds().get(0); + sender.sendMessage(I.t("{ci}From the console, generating the walls of the default world, {0}", world.getName())); + } + + try + { + p.getBorderManager().generateWalls(world); + + } + catch (CannotGenerateWallsException e) + { + sender.sendMessage(I.t("{ce}Unable to generate the wall: see logs for details. The blocks set in the config are probably invalid.")); + return; + + } + catch (Exception e) + { + sender.sendMessage(I.t("{ce}An error occurred, see console for details.")); + e.printStackTrace(); + return; + } + + sender.sendMessage(I.t("{cst}Generation done.")); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh generatewalls {ci}: generates the walls according to the configuration.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java new file mode 100644 index 0000000..3d02795 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java @@ -0,0 +1,148 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +/** + * This command feeds a player. + *

+ * Usage: /uh feed <player> [foodLevel=20] [saturation=20] + */ +@Command (name = "healall") +public class UHHealAllCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHHealAllCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + double diffHealth = 0D; + double health = 0D; + boolean add = false; // "add" (±, true) or "raw" (exact health, false) mode + + + if (args.length == 0) // /uh healall : full life for all players. + { + diffHealth = 20D; + } + else // /uh heal + { + try + { + if (args[0].startsWith("+")) + { + diffHealth = Double.parseDouble(args[0].substring(1)); + add = true; + } + else if (args[0].startsWith("-")) + { + diffHealth = -1 * Double.parseDouble(args[0].substring(1)); + add = true; + } + else + { + diffHealth = Double.parseDouble(args[0]); + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Hey, this is not a number of half-hearts. It's a text. Pfff.")); + return; + } + } + + if ((!add && diffHealth <= 0) || diffHealth <= -20) + { + sender.sendMessage(I.t("{ce}Serial killer!")); + return; + } + + + for (final Player player : p.getServer().getOnlinePlayers()) + { + health = !add ? diffHealth : player.getHealth() + diffHealth; + + if (health <= 0D) + { + sender.sendMessage(I.t("{ce}The health of {0} was not updated to avoid a kill.", player.getName())); + continue; + } + else if (health > 20D) + { + health = 20D; + } + + player.setHealth(health); + UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId()).updateHealth(health); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of only one.")); + } + + @Override + public String getCategory() + { + return Category.BUGS.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java new file mode 100644 index 0000000..9a6873c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java @@ -0,0 +1,151 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +/** + * This command heals a player. + * + * Usage: /uh heal + */ +@Command (name = "heal") +public class UHHealCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHHealCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length < 1 || args.length > 2) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + Player player = p.getServer().getPlayer(args[0]); + if (player == null || !player.isOnline()) + { + sender.sendMessage(I.t("{ce}This player is offline.")); + return; + } + + double health = 0D; + boolean add = false; // "add" (±, true) or "raw" (exact health, false) mode + + if (args.length == 1) + { // /uh heal : full life for player. + health = 20D; + } + else + { // /uh heal + double diffHealth; + + try + { + if (args[1].startsWith("+")) + { + diffHealth = Double.parseDouble(args[1].substring(1)); + add = true; + } + else if (args[1].startsWith("-")) + { + diffHealth = -1 * Double.parseDouble(args[1].substring(1)); + add = true; + } + else + { + diffHealth = Double.parseDouble(args[1]); + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}Hey, this is not a number of half-hearts. It's a text. Pfff.")); + return; + } + + health = !add ? diffHealth : player.getHealth() + diffHealth; + + if (health <= 0D) + { + sender.sendMessage(I.t("{ce}You can't kill a player with this command, to avoid typo fails.")); + return; + } + else if (health > 20D) + { + health = 20D; + } + } + + player.setHealth(health); + UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId()).updateHealth(health); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh heal [half-hearts=20|±diff] {ci}: heals a player to the number of half-hearts provided (default 20).")); + } + + @Override + public String getCategory() + { + return Category.BUGS.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java new file mode 100644 index 0000000..ca3cde1 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java @@ -0,0 +1,204 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.text.RawMessage; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +@Command (name = "infos") +public class UHInfosCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHInfosCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + CommandUtils.displaySeparator(sender); + + if (p.getGameManager().isGameStarted()) + { + /// Header of the /uh infos command. Plural based on the players count. + sender.sendMessage(I.tn("{ci}{0} player alive in {1} team.", "{ci}{0} players alive in {1} teams.", p.getGameManager().getAlivePlayersCount(), p.getGameManager().getAlivePlayersCount(), p.getGameManager().getAliveTeamsCount())); + } + else + { + sender.sendMessage(I.t("{ci}The game is not started.")); + } + + for (UHTeam team : p.getTeamManager().getTeams()) + { + for (OfflinePlayer player : team.getPlayers()) + { + if (sender instanceof Player) + { + /* We can use a JSON-based message */ + + String json = "{\"text\":\"\",\"extra\":["; + + + // Online/offline bullet + json += "{"; + if (player.isOnline()) + { + /// Online status dot in /uh infos + json += "\"text\":\"" + I.t("{green} • ") + "\","; + json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + I.t("Currently online") + "\"}"; + } + else + { + /// Offline status dot in /uh infos + json += "\"text\":\"" + I.t("{red} • ") + "\","; + json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + I.t("Currently offline") + "\"}"; + } + json += "},"; + + + // Name and team + json += "{"; + json += "\"text\":\"" + team.getColor().toChatColor() + player.getName() + ChatColor.RESET + "\","; + /// Team name in tooltip in /uh infos + json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + I.t("Team: {0}", team.getDisplayName()) + "\"}"; + json += "}"; + + + if (p.getGameManager().isGameStarted()) + { + /// Separator in /uh infos + json += ",{\"text\":\"" + I.t("{gray} - ") + "\"},"; + + // Alive state + json += "{"; + if (!p.getGameManager().isPlayerDead(player.getUniqueId())) + { + /// Alive state in /uh infos + json += "\"text\":\"" + I.t("{green}alive") + "\","; + if (player.isOnline()) + { + json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + I.t("{0} half-hearts", String.valueOf((int) ((Player) player).getHealth())) + "\"}"; + } + } + else + { + /// Alive state in /uh infos + json += "\"text\":\"" + I.t("{red}dead") + "\""; + } + json += "}"; + } + + // End + json += "]}"; + + RawMessage.send((Player) sender, json); + } + else + { + /* Fallback to a simple display for the console */ + + String info; + + if (player.isOnline()) + { + info = I.t("{green} • "); + } + else + { + info = I.t("{red} • "); + } + + info += team.getColor().toChatColor() + player.getName() + ChatColor.RESET; + + if (p.getGameManager().isGameStarted()) + { + info += I.t("{gray} - "); + + if (!p.getGameManager().isPlayerDead(player.getUniqueId())) + { + info += I.t("{green}alive"); + } + else + { + info += I.t("{red}dead"); + } + } + + sender.sendMessage(info); + } + } + } + + + CommandUtils.displaySeparator(sender); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh infos {ci}: prints some infos about the current game.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java new file mode 100644 index 0000000..800d74c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java @@ -0,0 +1,129 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This command marks a player as dead, even if he is offline. + * + * If the player is online, this has the same effect as {@code /kill}. + * + * Usage: /uh kill <player> + */ +@Command (name = "kill") +public class UHKillCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHKillCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length < 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + OfflinePlayer player = p.getServer().getOfflinePlayer(args[0]); + + if (player == null) + { + sender.sendMessage(I.t("{ce}This player was never seen on this server.")); + return; + } + + if (!p.getGameManager().isPlayerDead(player.getUniqueId())) + { + if (player.isOnline()) + { + ((Player) player).setHealth(0); + } + else + { + p.getGameManager().addDead(player.getUniqueId()); + } + + sender.sendMessage(I.t("{cs}The player {0} is now marked as dead.", player.getName())); + } + else + { + sender.sendMessage(I.t("{ce}{0} is not an alive player.", player.getName())); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + List suggestions = new ArrayList<>(); + + for (OfflinePlayer player : p.getGameManager().getAlivePlayers()) + { + suggestions.add(player.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh kill {ci}: mark a player as dead, even if he is offline.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java new file mode 100644 index 0000000..e7e63eb --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java @@ -0,0 +1,116 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; + + +@Command(name = "loadplayers") +public class UHLoadPlayersCommand extends AbstractCommand +{ + @Override + public void run(final CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!Bukkit.getOnlineMode()) + { + sender.sendMessage(I.t("{ce}You cannot load unknown players in offline mode, sorry.")); + return; + } + + if (args.length == 0) + { + /// Error returned if one calls /uh loadplayers without arguments. + sender.sendMessage(I.t("{ce}You need to provide at least one player name.")); + return; + } + + /// Message displayed when the /uh loadplayers command is used, as the execution may take some time. + sender.sendMessage(I.t("{cst}Loading players...")); + + OfflinePlayersLoader.loadPlayers(Arrays.asList(args), new Callback>() + { + @Override + public void call(Map addedPlayers) + { + sender.sendMessage(I.tn("{cs}Loaded {0} player successfully.", "{cs}Loaded {0} players successfully.", addedPlayers.size())); + } + }, new Callback>() + { + @Override + public void call(List notFound) + { + /// Message sent if some players cannot be loaded while /uh loadplayers is used. 0 = amount of players missing; 1 = list of nicknames (format "nick1, nick2, nick3"). + sender.sendMessage(I.tn("{ce}{0} player is missing: {1}.", "{ce}{0} players are missing: {1}.", notFound.size(), notFound.size(), StringUtils.join(notFound, ", "))); + } + }); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh loadplayers [pseudo] ... {ci}: loads the given players in the server so they can be added to teams even if they never logged in.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java new file mode 100644 index 0000000..2eaa039 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java @@ -0,0 +1,129 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This command resurrects a player. + * + * Usage: /uh resurrect + */ +@Command (name = "resurrect") +public class UHResurrectCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHResurrectCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length != 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + boolean success = p.getGameManager().resurrect(args[0]); + + Player player = p.getServer().getPlayer(args[0]); + if (player == null || !player.isOnline()) + { + if (!success) // Player does not exists or is nod dead. + { + sender.sendMessage(I.t("{ce}This player is not playing or dead!")); + } + else // Resurrected + { + sender.sendMessage(I.t("{cs}Because {0} is offline, he will be resurrected when he logins. If he was, he is no longer banned.", args[0])); + } + } + else + { + if (!success) // The player is not dead + { + /// Trying to resurrect an alive player + sender.sendMessage(I.t("{ce}{0} is not dead!", args[0])); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + List suggestions = new ArrayList<>(); + + // TODO can be optimized + for (String playerName : p.getGameManager().getPlayers()) + { + OfflinePlayer player = p.getServer().getOfflinePlayer(playerName); + if (player != null && p.getGameManager().isPlayerDead(player.getUniqueId())) + { + suggestions.add(playerName); + } + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh resurrect {ci}: resurrects a player.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java new file mode 100644 index 0000000..83b8688 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java @@ -0,0 +1,111 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +@Command (name = "rules") +public class UHRulesCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHRulesCommand(UHCReloaded plugin) + { + p = plugin; + } + + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!p.getRulesManager().isEnabled()) + { + sender.sendMessage(I.t("{ce}No rules are set in the config file.")); + return; + } + + if (args.length >= 1) + { + Player player = Bukkit.getPlayer(args[0]); + if (player != null) + { + p.getRulesManager().displayRulesTo(player); + + if (!sender.equals(player)) + sender.sendMessage(I.t("{cs}Rules sent to {0}.", player.getName())); + } + else + { + sender.sendMessage(I.t("{ce}Cannot display the rules to {0} because he (or she) is offline.", args[0])); + } + } + else + { + p.getRulesManager().broadcastRules(); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh rules [player] {ci}: sends the server rules to the server or the given player.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java new file mode 100644 index 0000000..27b9780 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java @@ -0,0 +1,99 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + +@Command (name = "shift") +public class UHShiftCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHShiftCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (p.getGameManager().isGameRunning()) + { + if (sender instanceof Player) + { + p.getGameManager().shiftEpisode((sender.getName())); + } + else + { + p.getGameManager().shiftEpisode(I.t("the console")); + } + } + else + { + sender.sendMessage(I.t("{ce}You can't shift the current episode because the game is not started.")); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh shift {ci}: shifts an episode.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java new file mode 100644 index 0000000..0ec9db5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java @@ -0,0 +1,108 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsAddCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsDumpCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsGenerateCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsListCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsRemoveCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns.UHSpawnsResetCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +@Command (name = "spawns") +public class UHSpawnsCommand extends AbstractCommand +{ + public UHSpawnsCommand(UHCReloaded plugin) + { + registerSubCommand(new UHSpawnsAddCommand(plugin)); + registerSubCommand(new UHSpawnsGenerateCommand(plugin)); + registerSubCommand(new UHSpawnsListCommand(plugin)); + registerSubCommand(new UHSpawnsDumpCommand(plugin)); + registerSubCommand(new UHSpawnsRemoveCommand(plugin)); + registerSubCommand(new UHSpawnsResetCommand(plugin)); + } + + /** + * This will be executed if this command is called without argument, + * or if there isn't any sub-command executor registered. + * + * @param sender The sender. + * @param args The arguments passed to the command. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + /** + * The result of this method will be added to the tab-complete suggestions for this command. + * + * @param sender The sender. + * @param args The arguments. + * + * @return The suggestions to add. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return Collections.singletonList(I.t("{aqua}------ Spawns points commands ------")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for details.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java new file mode 100644 index 0000000..98700c7 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java @@ -0,0 +1,211 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +/** + * This command manages startup spectators (aka ignored players). + * + * Usage: /uh spec (doc) + * Usage: /uh spec + */ +@Command (name = "spec") +public class UHSpectatorsCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpectatorsCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(final CommandSender sender, final String[] args) throws CannotExecuteCommandException + { + // /uh spec + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + else + { + String subcommand = args[0]; + + if (subcommand.equalsIgnoreCase("add")) + { + // /uh spec add + if (args.length == 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + // /uh spec add + else + { + OfflinePlayersLoader.loadPlayer(args[1], new Callback() + { + @Override + public void call(OfflinePlayer player) + { + if (player == null) + { + sender.sendMessage(I.t("{ce}Unable to retrieve the player {0}.")); + + if (!Bukkit.getOnlineMode()) + sender.sendMessage(I.t("{ce}In offline mode, you cannot add players if they never came to this server.")); + + return; + } + + p.getGameManager().addStartupSpectator(player); + sender.sendMessage(I.t("{cs}The player {0} is now a spectator.", player.getName())); + } + }); + } + } + + else if (subcommand.equalsIgnoreCase("remove")) + { + // /uh spec remove + if (args.length == 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + // /uh spec remove + else + { + OfflinePlayer oldSpectator = OfflinePlayersLoader.getOfflinePlayer(args[1]); + if (oldSpectator == null) + { + sender.sendMessage(I.t("{ce}The player {0} was not found.", args[1])); + } + else + { + p.getGameManager().removeStartupSpectator(oldSpectator); + sender.sendMessage(I.t("{cs}The player {0} is now a player.", args[1])); + } + } + } + + else if (subcommand.equalsIgnoreCase("list")) + { + HashSet spectators = p.getGameManager().getStartupSpectators(); + if (spectators.size() == 0) + { + sender.sendMessage(I.t("{ce}There isn't any spectator to list.")); + } + else + { + sender.sendMessage(I.tn("{ci}{0} registered spectator.", "{ci}{0} registered spectators.", spectators.size())); + sender.sendMessage(I.t("{ci}This count includes only the initial spectators.")); + + for (String spectator : spectators) + { + /// A list item in the startup spectators list + sender.sendMessage(I.tc("startup_specs", "{lightpurple} - {0}", spectator)); + } + } + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + // Manual suggestions needed because we don't use sub-commands. + if (args.length == 1) + { + return CommandUtils.getAutocompleteSuggestions(args[0], Arrays.asList("add", "remove", "list")); + } + + // /... spec remove + else if (args.length == 2 && args[1].equalsIgnoreCase("remove")) + { + List suggestions = new ArrayList<>(); + + for (String spectatorName : p.getGameManager().getStartupSpectators()) + { + suggestions.add(spectatorName); + } + + return CommandUtils.getAutocompleteSuggestions(args[1], suggestions); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + List help = new ArrayList<>(); + + help.add(I.t("{aqua}------ Startup spectators commands ------")); + + help.add(I.t("{cc}/uh spec add {ci}: adds a startup spectator.")); + help.add(I.t("{cc}/uh spec remove {ci}: removes a startup spectator.")); + help.add(I.t("{cc}/uh spec list{ci}: lists the startup spectators.")); + + return help; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java new file mode 100644 index 0000000..80dc3a0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java @@ -0,0 +1,153 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This command starts the game. + * + * Usage: /uh start [slow:true] [ignoreTeams:true] + */ +@Command (name = "start") +public class UHStartCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHStartCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 1 && args[0].equalsIgnoreCase("help")) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + else if (p.getGameManager().isSlowStartInProgress()) + { + p.getGameManager().finalizeStartSlow(sender); + return; + } + + final Map defaultTags = new HashMap<>(); + defaultTags.put("slow", "false"); + defaultTags.put("ignoreTeams", "false"); + + final Map tags = CommandUtils.getTagsInArgs(args, defaultTags); + + try + { + p.getGameManager().start(sender, UHUtils.stringToBoolean(tags.get("slow")), UHUtils.stringToBoolean(tags.get("ignoreTeams"))); + } + catch (IllegalStateException e) + { + sender.sendMessage(I.t("{ce}The game is already started! Reload or restart the server to restart the game.")); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + final List suggestions = new ArrayList<>(); + + suggestions.add("slow:true"); + suggestions.add("ignoreTeams:true"); + + if (args.length == 1) + suggestions.add("help"); + + return CommandUtils.getAutocompleteSuggestions(args[args.length - 1], suggestions); + } + + @Override + public List help(CommandSender sender) + { + return Arrays.asList( + I.t("{aqua}------ Beginning of the game ------"), + I.t("{cc}/uh start {ci}: starts the game. Period."), + I.t("{aqua}Startup options"), + I.t("{ci}You can add some tags to change the way the game is started, just append them to the command with spaces."), + I.t("{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation then beginning of the game), for smaller servers."), + I.t("{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a solo game (only one player per spawn point, not a spawn point per team).") + ); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh start {ci}: launches the game. See /uh start help for options (slow and ignoreTeams).")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java new file mode 100644 index 0000000..cc18f3c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java @@ -0,0 +1,137 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Command (name = "tpback") +public class UHTPBackCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTPBackCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length < 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + Player player = p.getServer().getPlayer(args[0]); + if (player == null || !player.isOnline()) + { + sender.sendMessage(I.t("{ce}The player {0} is not online.", args[0])); + return; + } + else if (!p.getGameManager().hasDeathLocation(player)) + { + sender.sendMessage(I.t("{ce}No death location available for the player {0}.", args[0])); + return; + } + + + Location deathLocation = p.getGameManager().getDeathLocation(player); + + if (args.length >= 2 && args[1].equalsIgnoreCase("force")) + { + UHUtils.safeTP(player, deathLocation, true); + sender.sendMessage(I.t("{cs}The player {0} was teleported back.", args[0])); + p.getGameManager().removeDeathLocation(player); + } + else if (UHUtils.safeTP(player, deathLocation)) + { + sender.sendMessage(I.t("{cs}The player {0} was teleported back.", args[0])); + p.getGameManager().removeDeathLocation(player); + } + else + { + sender.sendMessage(I.t("{ce}The player {0} was NOT teleported back because no safe spot was found.", args[0])); + sender.sendMessage(I.t("{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this point.", args[0])); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + List suggestions = new ArrayList<>(); + + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getGameManager().hasDeathLocation(player)) + { + suggestions.add(player.getName()); + } + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + } + + else if (args.length == 2) + { + return CommandUtils.getAutocompleteSuggestions(args[1], Collections.singletonList("force")); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh tpback [force] {ci}: safely teleports back a player to his death location.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java new file mode 100644 index 0000000..cdfb4b6 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java @@ -0,0 +1,280 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * This command teleports a team or the spectators to a given location. + * + * Usage: /uh tp team + * Usage: /uh tp team + * Usage: /uh tp spectators + * Usage: /uh tp spectators + */ +@Command (name = "tp") +public class UHTPCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTPCommand(UHCReloaded plugin) + { + this.p = plugin; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + // No action provided: doc + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + else + { + String subcommand = args[0]; + + World targetWorld; + if (sender instanceof Player) + { + targetWorld = ((Player) sender).getWorld(); + } + else if (sender instanceof BlockCommandSender) + { + targetWorld = ((BlockCommandSender) sender).getBlock().getWorld(); + } + else + { + targetWorld = p.getServer().getWorlds().get(0); + } + + if (subcommand.equalsIgnoreCase("team")) + { + boolean mayBeNaNError = false; + + // possibly /uh tp team + if (args.length >= 6) + { + String teamName = UHUtils.getStringFromCommandArguments(args, 4); + UHTeam team = p.getTeamManager().getTeam(teamName); + + // ok, the team exists. + if (team != null) + { + try + { + double x = Integer.parseInt(args[1]) + 0.5; + double y = Integer.parseInt(args[2]) + 0.5; + double z = Integer.parseInt(args[3]) + 0.5; + + team.teleportTo(new Location(targetWorld, x, y, z)); + + return; + } + catch (NumberFormatException e) + { + // It can be either another name for the team, starting by " the name" + // or a formatting error. + // The possibility of an error is saved. + mayBeNaNError = true; + } + } + } + + // /uh tp team + if (args.length >= 3) + { + String teamName = UHUtils.getStringFromCommandArguments(args, 2); + UHTeam team = p.getTeamManager().getTeam(teamName); + + if (team == null) + { + if (mayBeNaNError) + { + sender.sendMessage(I.t("{ce}The coordinates must be three valid numbers.")); + } + else + { + sender.sendMessage(I.t("{ce}This team is not registered.")); + } + } + else + { + Player target = p.getServer().getPlayer(args[1]); + + if (target == null) + { + sender.sendMessage(I.t("{ce}{0} is offline!", args[1])); + } + else + { + team.teleportTo(target.getLocation()); + } + } + } + } + + else if (subcommand.equalsIgnoreCase("spectators")) + { + // /uh tp spectators + if (args.length == 4) + { + try + { + double x = Integer.parseInt(args[1]) + 0.5; + double y = Integer.parseInt(args[2]) + 0.5; + double z = Integer.parseInt(args[3]) + 0.5; + + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getGameManager().isPlayerDead(player)) + { + player.teleport(new Location(targetWorld, x, y, z), PlayerTeleportEvent.TeleportCause.PLUGIN); + } + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}The coordinates must be three valid numbers.")); + } + } + + // /uh tp spectators + else if (args.length == 2) + { + Player target = p.getServer().getPlayer(args[1]); + + if (target == null) + { + sender.sendMessage(I.t("{ce}{0} is offline!", args[1])); + } + else + { + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getGameManager().isPlayerDead(player)) + { + player.teleport(target.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN); + } + } + } + } + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + + if (args.length == 1) + { + return CommandUtils.getAutocompleteSuggestions( + args[0], + Arrays.asList("team", "spectators") + ); + } + + else if (args.length > 1 && args[0].equalsIgnoreCase("team")) + { + ArrayList teamNames = new ArrayList<>(); + for (UHTeam team : this.p.getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + // /uh tp team : autocompletion for team names – multiple words autocompletion + if (args.length >= 5) + { + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 4), teamNames, args.length - 5); + } + + // /uh tp team : autocompletion for team names – multiple words autocompletion + if (args.length >= 3) + { + try + { + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 2), teamNames, args.length - 3); + } + catch (IllegalArgumentException ignored) + { + // Temp workaround for an unknown bug. + } + } + } + + return null; + } + + @Override + public List help(CommandSender sender) + { + return Arrays.asList( + I.t("{aqua}------ Teleportation commands ------"), + I.t("{cc}/uh tp team | {ci}: teleports the team to the given location/target."), + I.t("{cc}/uh tp spectators | {ci}: teleports the spectators (aka non-alive players) to the given location/target.") + ); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for details.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java new file mode 100644 index 0000000..2341887 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java @@ -0,0 +1,150 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Command (name = "tpspawn") +public class UHTPSpawnCommand extends AbstractCommand +{ + private final UHCReloaded p; + + public UHTPSpawnCommand(UHCReloaded plugin) + { + p = plugin; + } + + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + // Spawns not assigned + if (p.getGameManager().getTeleporter() == null) + { + sender.sendMessage(I.t("{ce}The spawn points are not already assigned to the player, because the game is not started.")); + return; + } + + + if (args.length < 1) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + Player player = p.getServer().getPlayer(args[0]); + if (player == null || !player.isOnline()) + { + sender.sendMessage(I.t("{ce}The player {0} is not online.", args[0])); + return; + } + + Location spawnLocation = p.getGameManager().getTeleporter().getSpawnForPlayer(player.getUniqueId()); + + if (spawnLocation == null) + { + sender.sendMessage(I.t("{ce}No spawn location available for the player {0}.", args[0])); + return; + } + + + if (args.length >= 2 && args[1].equalsIgnoreCase("force")) + { + p.getGameManager().getTeleporter().teleportPlayer(player.getUniqueId(), true); + sender.sendMessage(I.t("{cs}The player {0} was teleported to his spawn location.", args[0])); + } + else if (UHUtils.safeTP(player, spawnLocation)) + { + sender.sendMessage(I.t("{cs}The player {0} was teleported to his spawn location.", args[0])); + } + else + { + sender.sendMessage(I.t("{ce}The player {0} was NOT teleported to his spawn because no safe spot was found.", args[0])); + sender.sendMessage(I.t("{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this point.", args[0])); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + // Spawns not attributed + if (p.getGameManager().getTeleporter() == null) + return null; + + + if (args.length == 1) + { + List suggestions = new ArrayList<>(); + + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getGameManager().getTeleporter().hasSpawnForPlayer(player.getUniqueId())) + { + suggestions.add(player.getName()); + } + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + } + + else if (args.length == 2) + { + return CommandUtils.getAutocompleteSuggestions(args[1], Collections.singletonList("force")); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh tpspawn [force] {ci}: safely teleports back a player to his spawn location.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java new file mode 100644 index 0000000..8ba51f0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java @@ -0,0 +1,127 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamAddCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamBannerCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamBannerResetCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamGUICommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamJoinCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamLeaveCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamListCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamRemoveCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamResetCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.team.UHTeamSpyCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * This command is used to manage the teams. + * + * Usage: /uh team (for the doc). + * Usage: /uh team (see doc for details). + */ +@Command (name = "team") +public class UHTeamCommand extends AbstractCommand +{ + public UHTeamCommand(UHCReloaded plugin) + { + registerSubCommand(new UHTeamAddCommand(plugin)); + registerSubCommand(new UHTeamRemoveCommand(plugin)); + registerSubCommand(new UHTeamJoinCommand(plugin)); + registerSubCommand(new UHTeamLeaveCommand(plugin)); + registerSubCommand(new UHTeamBannerCommand()); + registerSubCommand(new UHTeamBannerResetCommand()); + registerSubCommand(new UHTeamListCommand(plugin)); + registerSubCommand(new UHTeamSpyCommand(plugin)); + registerSubCommand(new UHTeamResetCommand(plugin)); + registerSubCommand(new UHTeamGUICommand(plugin)); + } + + /** + * This will be executed if this command is called without argument, + * or if there isn't any sub-command executor registered. + * + * @param sender The sender. + * @param args The arguments passed to the command. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + /** + * The result of this method will be added to the tab-complete suggestions for this command. + * + * @param sender The sender. + * @param args The arguments. + * + * @return The suggestions to add. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return Arrays.asList( + I.t("{aqua}------ Team commands ------"), + I.t("{cc}/join [player] {ci}: adds “player” (or the sender) inside the given team. Without arguments, displays the chat-based team selector."), + I.t("{cc}/leave [player] {ci}: removes “player” (or the sender) from his team.") + ); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team {ci}: manages the teams. Execute /uh team for details.")); + } + + @Override + public String getCategory() + { + return Category.GAME.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java new file mode 100644 index 0000000..c137550 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java @@ -0,0 +1,106 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.commands.categories.Category; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersAddCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersDisplayCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersHideCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersListCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersPauseCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersRemoveCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersResumeCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersSetCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersStartCommand; +import eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers.UHTimersStopCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +/** + * This command manages timers. + * + * Usage: /uh timers < add | set | display | hide | start | pause | resume | stop | remove | list > + */ +@Command (name = "timers") +public class UHTimersCommand extends AbstractCommand +{ + public UHTimersCommand(UHCReloaded plugin) + { + registerSubCommand(new UHTimersAddCommand(plugin)); + registerSubCommand(new UHTimersSetCommand(plugin)); + registerSubCommand(new UHTimersDisplayCommand(plugin)); + registerSubCommand(new UHTimersHideCommand(plugin)); + registerSubCommand(new UHTimersStartCommand(plugin)); + registerSubCommand(new UHTimersPauseCommand(plugin)); + registerSubCommand(new UHTimersResumeCommand(plugin)); + registerSubCommand(new UHTimersStopCommand(plugin)); + registerSubCommand(new UHTimersRemoveCommand(plugin)); + registerSubCommand(new UHTimersListCommand(plugin)); + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return Collections.singletonList(I.t("{aqua}------ Timers commands ------")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers {ci}: manages the timers. See /uh timers for details.")); + } + + @Override + public String getCategory() + { + return Category.MISC.getTitle(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java new file mode 100644 index 0000000..4e69309 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java @@ -0,0 +1,93 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.border; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +@Command (name = "check") +public class UHBorderCheckCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHBorderCheckCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { // /uh border check + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + else + { // /uh border check + try + { + Integer checkDiameter = Integer.valueOf(args[0]); + p.getBorderManager().sendCheckMessage(sender, checkDiameter); + + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}“{0}” is not a number...", args[0])); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh border check {ci}: returns a list of the players outside the given border size.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java new file mode 100644 index 0000000..135df11 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java @@ -0,0 +1,85 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.border; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +@Command (name = "get") +public class UHBorderGetCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHBorderGetCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + sender.sendMessage(I.tn("{ci}The current diameter of the map is {0} block.", "{ci}The current diameter of the map is {0} blocks.", p.getBorderManager().getCurrentBorderDiameter())); + } + else + { + sender.sendMessage(I.t("{ci}The current map size is {0}×{0}.", p.getBorderManager().getCurrentBorderDiameter())); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh border get{ci}: returns the current size of the map.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java new file mode 100644 index 0000000..ee1ef44 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java @@ -0,0 +1,149 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.border; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +@Command (name = "set") +public class UHBorderSetCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHBorderSetCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + // /uh border set + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + // /uh border set + else if (args.length == 1) + { + try + { + Integer newDiameter = Integer.valueOf(args[0]); + + if (p.getBorderManager().getPlayersOutside(newDiameter).size() != 0) + { // Some players are outside + sender.sendMessage(I.t("{ce}Some players are outside the future border, so this operation was cancelled.")); + sender.sendMessage(I.t("{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to this point.", args[0])); + if (!p.getWorldBorderIntegration().isWBIntegrationEnabled()) + { + sender.sendMessage(I.t("{ce}WARNING: {ci}because WorldBorder is not installed, players out of the border will not be teleported!")); + } + p.getBorderManager().sendCheckMessage(sender, newDiameter); + } + else + { + p.getBorderManager().setCurrentBorderDiameter(newDiameter); + + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + p.getServer().broadcastMessage(I.tn("{lightpurple}The diameter of the map is now {0} block.", "{lightpurple}The diameter of the map is now {0} blocks.", newDiameter)); + } + else + { + p.getServer().broadcastMessage(I.t("{lightpurple}The size of the map is now {0}×{0}.", newDiameter)); + } + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}“{0}” is not a number...", args[0])); + } + } + + // /uh border set force + else if (args.length == 2 && args[1].equalsIgnoreCase("force")) + { + try + { + Integer newDiameter = Integer.valueOf(args[0]); + + p.getBorderManager().setCurrentBorderDiameter(newDiameter); + + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + p.getServer().broadcastMessage(I.tn("{lightpurple}The diameter of the map is now {0} block.", "{lightpurple}The diameter of the map is now {0} blocks.", newDiameter)); + } + else + { + p.getServer().broadcastMessage(I.t("{lightpurple}The size of the map is now {0}×{0}.", newDiameter)); + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}“{0}” is not a number...", args[0])); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 2) + { + return CommandUtils.getAutocompleteSuggestions(args[1], Collections.singletonList("force")); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh border set [force]{ci}: changes the size of the map. If force is not given, the operation will be canceled if there is a player outside the border.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java new file mode 100644 index 0000000..3f9c2a9 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java @@ -0,0 +1,120 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.border; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +@Command (name = "warning") +public class UHBorderWarningCommand extends AbstractCommand +{ + private final Integer WARNING_INTERVAL; + + private final UHCReloaded p; + + + public UHBorderWarningCommand(UHCReloaded p) + { + this.p = p; + + WARNING_INTERVAL = UHConfig.MAP.BORDER.WARNING_INTERVAL.get(); + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { // /uh border warning + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + else if (args[0].equalsIgnoreCase("cancel")) + { // /uh border warning cancel + p.getBorderManager().cancelWarning(); + sender.sendMessage(I.t("{cs}Warning canceled.")); + } + else + { // /uh border warning + try + { + Integer warnDiameter = Integer.valueOf(args[0]); + + Integer warnTime = 0; + if (args.length >= 4) + { // /uh border warning + warnTime = Integer.valueOf(args[1]); + } + + p.getBorderManager().setWarningSize(warnDiameter, warnTime, sender); + sender.sendMessage(I.tn("{cs}Future size saved. All players outside this future border will be warned every {0} second.", "{cs}Future size saved. All players outside this future border will be warned every {0} seconds.", WARNING_INTERVAL)); + + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}“{0}” is not a number...", args[0])); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + return CommandUtils.getAutocompleteSuggestions(args[0], Collections.singletonList("cancel")); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Arrays.asList(I.t("{cc}/uh border warning [minutesBeforeReduction]{ci}: warns all players outside the given future diameter. It's just a notice, nothing else."), I.t("{cc}/uh border warning cancel{ci}: cancels a previously-set warning.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java new file mode 100644 index 0000000..1b8f095 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java @@ -0,0 +1,160 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.World; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "add") +public class UHSpawnsAddCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsAddCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + + // World? + World world; + if (sender instanceof Player) + { + world = ((Player) sender).getWorld(); + } + else if (sender instanceof BlockCommandSender) + { + world = ((BlockCommandSender) sender).getBlock().getWorld(); + } + else + { + world = p.getServer().getWorlds().get(0); + } + + if (args.length == 0) + { // /uh spawns add + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + else + { + Player pl = (Player) sender; // Just a way to avoid casts everywhere. + try + { + p.getSpawnsManager().addSpawnPoint(pl.getLocation()); + sender.sendMessage(I.t("{cs}Spawn added in the world {0}: {1};{2}", world.getName(), String.valueOf(pl.getLocation().getBlockX()), String.valueOf(pl.getLocation().getBlockZ()))); + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}You cannot add a spawn point out of the borders.")); + } + catch (RuntimeException e) + { + sender.sendMessage(I.t("{ce}Unable to add this spawn point: no safe spot found in the Nether.")); + } + } + } + else if (args.length == 1) + { // /uh spawns add : Two coordinates needed! + sender.sendMessage(I.t("{ce}You need to specify two coordinates.")); + } + else + { // /uh spawns add + try + { + p.getSpawnsManager().addSpawnPoint(world, Double.parseDouble(args[0]), Double.parseDouble(args[1])); + sender.sendMessage(I.t("{cs}Spawn added in the world {0}: {1};{2}", world.getName(), args[0], args[1])); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}This is not a number!")); + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}You cannot add a spawn point out of the borders.")); + } + catch (RuntimeException e) + { + sender.sendMessage(I.t("{ce}Unable to add this spawn point: no safe spot found in the Nether.")); + } + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the current location of the sender or at the provided coordinates.")); + } + + @Override + public List onListHelp(CommandSender sender) + { + return null; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java new file mode 100644 index 0000000..56d3904 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java @@ -0,0 +1,128 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +@Command (name = "dump") +public class UHSpawnsDumpCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsDumpCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + // We want one list per world + Map> spanwsInWorlds = new HashMap>(); + for (World world : p.getServer().getWorlds()) + { + spanwsInWorlds.put(world, new LinkedList()); + } + + for (Location spawn : p.getSpawnsManager().getSpawnPoints()) + { + spanwsInWorlds.get(spawn.getWorld()).add(spawn); + } + + String dump = ""; + + for (Map.Entry> spanwsInWorld : spanwsInWorlds.entrySet()) + { + if (spanwsInWorld.getValue().size() == 0) + { + continue; + } + + dump += "\n* " + spanwsInWorld.getKey().getName() + "\n"; + + for (Location spawn : spanwsInWorld.getValue()) + { + dump += spawn.getBlockX() + "," + spawn.getBlockZ() + "\n"; + } + } + + sender.sendMessage(dump); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns dump {ci}: displays the registered spawn points in an exportable format. {gray}Use this to plot the spawn points, as example.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java new file mode 100644 index 0000000..56902c5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java @@ -0,0 +1,297 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.spawns.Generator; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.UnknownGeneratorException; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.World; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +@Command (name = "generate") +public class UHSpawnsGenerateCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsGenerateCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + + if (args.length == 0) + { // Help + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NEED_DOC, this); + } + + String generationMethod = args[0]; + + // Default values + Integer size = p.getBorderManager().getCurrentBorderDiameter() - 25; // Avoid spawn points being too close to the border + Integer distanceMinBetweenTwoPoints = 250; + World world = p.getServer().getWorlds().get(0); + Double xCenter = world.getSpawnLocation().getX(); + Double zCenter = world.getSpawnLocation().getZ(); + + Integer spawnsCount = 0; + for (UHTeam team : p.getTeamManager().getTeams()) + { + if (!team.isEmpty()) spawnsCount++; + } + + if (args.length < 7) + { + if (sender instanceof Player) + { + world = ((Player) sender).getWorld(); + } + else if (sender instanceof BlockCommandSender) + { + world = ((BlockCommandSender) sender).getBlock().getWorld(); + } + + xCenter = world.getSpawnLocation().getX(); + zCenter = world.getSpawnLocation().getZ(); + } + + // What if the game is in solo, or some players are out of all team? + // Only if the spawn count is not provided of course. Else, we don't care, this count + // will be overwritten. + if (args.length < 5) + { + if (spawnsCount == 0) + { // Solo mode? + sender.sendMessage(I.t("{ci}No team found: assuming the game is a solo game.")); + spawnsCount = p.getServer().getOnlinePlayers().size() - p.getGameManager().getStartupSpectators().size(); + } + else + { + // Trying to find players without team + int playersWithoutTeam = 0; + for (Player player : p.getServer().getOnlinePlayers()) + { + if (p.getTeamManager().getTeamForPlayer(player) == null) + { + playersWithoutTeam++; + } + } + + if (playersWithoutTeam != 0) + { + sender.sendMessage(I.t("{ci}Some players are not in a team; their number was added to the spawn count.")); + spawnsCount += playersWithoutTeam; + } + } + } + + try + { + if (args.length >= 2) + { // size included + size = Integer.valueOf(args[1]); + + if (args.length >= 3) + { // distance minimal included + distanceMinBetweenTwoPoints = Integer.valueOf(args[2]); + + if (args.length >= 4) + { // spawn count included + spawnsCount = Integer.valueOf(args[3]); + + if (args.length >= 5) + { // xCenter included + xCenter = Double.parseDouble(args[4]); + + if (args.length >= 6) + { // zCenter included + zCenter = Double.parseDouble(args[5]); + + if (args.length >= 7) + { // world included + World inputWorld = p.getServer().getWorld(args[6]); + + if (inputWorld != null) + { + world = inputWorld; + } + else + { + sender.sendMessage(I.t("{ce}The world {0} doesn't exists.", args[6])); + return; + } + } + } + } + } + } + } + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}This is not a number!")); + return; + } + + + if (spawnsCount <= 0) + { + sender.sendMessage(I.t("{ci}You asked for a void generation. Thus, the generation is empty.")); + return; + } + + + try + { + p.getSpawnsManager().generateSpawnPoints(generationMethod, world, spawnsCount, size, distanceMinBetweenTwoPoints, xCenter, zCenter); + + } + catch (UnknownGeneratorException e) + { + sender.sendMessage(I.t("{ce}The generation method “{0}” is not (yet?) supported.", generationMethod)); + return; + + } + catch (CannotGenerateSpawnPointsException e) + { + sender.sendMessage(I.t("{ce}You asked for the impossible: there are too many spawn points on a too small surface. Decrease the spawn count or the minimal distance between two points.")); + return; + } + + sender.sendMessage(I.t("{cs}Successfully generated the asked spawn points.")); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + // Generation methods - /uh spawns generate + if (args.length == 1) + { + ArrayList suggested = new ArrayList(); + + for (Generator generator : Generator.values()) + { + suggested.add(generator.name().toLowerCase()); + } + + return CommandUtils.getAutocompleteSuggestions(args[0], suggested); + } + + // Worlds - /uh spawns generate - - - - - - + else if (args.length == 7) + { + ArrayList suggested = new ArrayList(); + for (World world : p.getServer().getWorlds()) + { + suggested.add(world.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(args[6], suggested); + } + + else return null; + } + + /** + * Returns the help of this command. + *

+ *

+ * The first line should describe briefly the command, as this line is displayed as + * a line of the help of the parent command. + *

+ *

+ * The other lines will only be displayed if the {@link eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException} + * is caught by the command executor. + *

+ * + * @param sender The sender. + * + * @return The help. One line per entry in the list. + */ + @Override + public List help(CommandSender sender) + { + return Arrays.asList( + I.t("{aqua}Command"), + I.t("{cc}/uh spawns generate [size] [distanceMin] [count] [xCenter] [zCenter] [world]"), + I.t("{aqua}Shapes"), + I.t(" - {cc}random{ci}: generates random spawn points on the map, with a minimal distance between them."), + I.t(" - {cc}grid{ci}: generates the spawn points on concentric squares, with a constant distance between two generated points."), + I.t(" - {cc}circular{ci}: generates the spawn points on concentric circles, with a minimal distance between two generated points. In each circle, the angle (and the distance) between two spawn points is constant."), + I.t("{aqua}Arguments"), + I.t(" - {cc}size{ci}: the size of the region where the spawn points will be generated. Squared or circular, following the shape of the map. Default: map' size."), + I.t(" - {cc}distanceMin{ci}: the minimal distance between two spawn points. Default: 250 blocks."), + I.t(" - {cc}count{ci}: the number of spawn points to generate. Default: the number of players or teams."), + I.t(" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the points are generated. Default: world' spawn point."), + I.t(" - {cc}world{ci}: the world where the spawn points will be generated.") + ); + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh spawns generate for details.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java new file mode 100644 index 0000000..520e0ab --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java @@ -0,0 +1,187 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +@Command (name = "list") +public class UHSpawnsListCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsListCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + List spawnPoints = p.getSpawnsManager().getSpawnPoints(); + + if (spawnPoints.size() == 0) + { + sender.sendMessage(I.t("{ce}There isn't any registered spawn point.")); + } + else + { + sender.sendMessage(I.t("{ci}There are {0} registered spawn points.", String.valueOf(spawnPoints.size()))); + + // We want one list per world + Map> spanwsInWorlds = new HashMap>(); + for (World world : p.getServer().getWorlds()) + { + spanwsInWorlds.put(world, new LinkedList()); + } + + for (Location spawn : spawnPoints) + { + spanwsInWorlds.get(spawn.getWorld()).add(spawn); + } + + for (Map.Entry> spanwsInWorld : spanwsInWorlds.entrySet()) + { + if (spanwsInWorld.getValue().size() == 0) + { + continue; + } + + sender.sendMessage(I.t("{lightpurple}World {0}", spanwsInWorld.getKey().getName())); + + + // Displaying this number of spawn points per line + final Integer spawnsPerLine = 5; + + for (int j = 0; j < Math.ceil((double) spanwsInWorld.getValue().size() / spawnsPerLine); j++) + { + String line = ""; + + for (int k = 0; k < spawnsPerLine; k++) + { + if (spawnPoints.size() > j * spawnsPerLine + k) + { + line += getSpawnItem(spanwsInWorld.getValue().get(j * spawnsPerLine + k).getBlockX(), spanwsInWorld.getValue().get(j * spawnsPerLine + k).getBlockZ(), spanwsInWorld.getKey().getEnvironment()) + " "; + } + } + + sender.sendMessage(line); + } + } + } + } + + private String getSpawnItem(int x, int z, World.Environment environment) + { + switch (environment) + { + case NORMAL: + /// A spawn point in the /uh spawns list command (in the overworld) + return I.t("{green}{0}{darkgreen};{green}{1}", x, z); + + case NETHER: + /// A spawn point in the /uh spawns list command (in the Nether) + return I.t("{red}{0}{darkred};{red}{1}", x, z); + + case THE_END: + /// A spawn point in the /uh spawns list command (in the End) + return I.t("{yellow}{0}{gold};{yellow}{1}", x, z); + + default: + /// A spawn point in the /uh spawns list command (in a custom world) + return I.t("{gray}{0}{darkgray};{gray}{1}", x, z); + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + /** + * Returns the help of this command. + *

+ *

+ * The first line should describe briefly the command, as this line is displayed as + * a line of the help of the parent command. + *

+ *

+ * The other lines will only be displayed if the {@link eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException} + * is caught by the command executor. + *

+ * + * @param sender The sender. + * + * @return The help. One line per entry in the list. + */ + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns list {ci}: lists the registered spawn points.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java new file mode 100644 index 0000000..0772056 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java @@ -0,0 +1,136 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "remove") +public class UHSpawnsRemoveCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsRemoveCommand(UHCReloaded plugin) + { + p = plugin; + } + + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { // /uh spawns remove + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + else + { + Player pl = (Player) sender; // Just a way to avoid casts everywhere. + p.getSpawnsManager().removeSpawnPoint(pl.getLocation(), false); + sender.sendMessage(I.t("{cs}The spawn point {1};{2} in the world {0} was removed.", pl.getWorld().getName(), String.valueOf(pl.getLocation().getBlockX()), String.valueOf(pl.getLocation().getBlockZ()))); + } + } + else if (args.length == 1) + { // /uh spawns add : Two coordinates needed! + sender.sendMessage(I.t("{ce}You need to specify two coordinates.")); + } + else + { // /uh spawns remove + try + { + World world; + if (sender instanceof Player) + { + world = ((Player) sender).getWorld(); + } + else + { + world = p.getServer().getWorlds().get(0); + } + + p.getSpawnsManager().removeSpawnPoint(new Location(world, Double.parseDouble(args[2]), 0, Double.parseDouble(args[3])), true); + sender.sendMessage(I.t("{cs}The spawn point {1};{2} in the world {0} was removed.", p.getServer().getWorlds().get(0).getName(), args[2], args[3])); + } + catch (NumberFormatException e) + { + sender.sendMessage(I.t("{ce}This is not a number!")); + } + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns remove [ ] {ci}: removes the spawn points at the specified coordinates, or at the current location if the sender without coordinates.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java new file mode 100644 index 0000000..f093f0f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java @@ -0,0 +1,95 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "reset") +public class UHSpawnsResetCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHSpawnsResetCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + p.getSpawnsManager().reset(); + sender.sendMessage(I.t("{cs}All the spawn points were removed.")); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh spawns reset {ci}: removes all registered spawn points.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java new file mode 100644 index 0000000..0264bdf --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java @@ -0,0 +1,165 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +@Command (name = "add") +public class UHTeamAddCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamAddCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 1) + { // /uh team add + + TeamColor color = TeamColor.fromString(args[0]); + UHTeam team; + + if (color == null) + { + sender.sendMessage(I.t("{ce}Unable to add the team, check the color name. Tip: use Tab to autocomplete.")); + } + else + { + try + { + team = p.getTeamManager().addTeam(color); + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}This team already exists.")); + return; + } + + sender.sendMessage(I.t("{cs}Team {0}{cs} added.", team.getDisplayName())); + } + + } + else if (args.length >= 2) + { // /uh team add + + TeamColor color = TeamColor.fromString(args[0]); + UHTeam team; + + if (color == null) + { + sender.sendMessage(I.t("{ce}Unable to add the team, check the color name. Tip: use Tab to autocomplete.")); + } + else + { + String name = UHUtils.getStringFromCommandArguments(args, 1); + + try + { + team = p.getTeamManager().addTeam(color, name); + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}This team already exists.")); + return; + } + + sender.sendMessage(I.t("{cs}Team {0}{cs} added.", team.getDisplayName())); + } + + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + if (args.length == 1) + { + List colors = Arrays.asList("aqua", "black", "blue", "darkaqua", + "darkblue", "darkgray", "darkgreen", "darkpurple", "darkred", + "gold", "gray", "green", "lightpurple", "red", "white", "yellow", "?"); + + return CommandUtils.getAutocompleteSuggestions(args[0], colors); + } + + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team add [] {ci}: adds a team with the provided color.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java new file mode 100644 index 0000000..3513ed0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java @@ -0,0 +1,111 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "banner") +public class UHTeamBannerCommand extends AbstractCommand +{ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!(sender instanceof Player)) + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER, this); + + UHTeam team; + + if (args.length >= 1) + { + String name = UHUtils.getStringFromCommandArguments(args, 0); + team = UHCReloaded.get().getTeamManager().getTeam(name); + } + else + { + team = UHCReloaded.get().getTeamManager().getTeamForPlayer((Player) sender); + } + + if (team == null) + { + sender.sendMessage(I.t("{ce}Either this team does not exists, or you are not in a team.")); + } + else if (((Player) sender).getItemInHand().getType() != Material.BANNER) + { + sender.sendMessage(I.t("{ce}You must run this command with a banner in your main hand.")); + } + else + { + team.setBanner(((Player) sender).getItemInHand()); + sender.sendMessage(I.t("{cs}The banner of the team {0}{cs} was successfully updated.", team.getDisplayName())); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + ArrayList teamNames = new ArrayList<>(); + + for (UHTeam team : UHCReloaded.get().getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team banner [team name ...] {ci}: updates the team's banner using the banner in the sender hand. If the team name is not provided, uses the sender's team.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java new file mode 100644 index 0000000..c203289 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java @@ -0,0 +1,110 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.bukkit.inventory.ItemStack; + + +@Command (name = "bannerreset") +public class UHTeamBannerResetCommand extends AbstractCommand +{ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + UHTeam team = null; + + if (args.length >= 1) + { + String name = UHUtils.getStringFromCommandArguments(args, 0); + team = UHCReloaded.get().getTeamManager().getTeam(name); + } + else if (sender instanceof Player) + { + team = UHCReloaded.get().getTeamManager().getTeamForPlayer((Player) sender); + } + else + { + /// Error message of /uh team bannerreset from the console without name + sender.sendMessage(I.t("{ce}From the console, you must provide a team name.")); + } + + + if (team == null) + { + sender.sendMessage(I.t("{ce}Either this team does not exists, or you are not in a team.")); + } + else + { + team.setBanner((ItemStack) null); + sender.sendMessage(I.t("{cs}The banner of the team {0}{cs} was successfully reset to the default one.", team.getDisplayName())); + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + ArrayList teamNames = new ArrayList<>(); + + for (UHTeam team : UHCReloaded.get().getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team bannerreset [team name ...] {ci}: resets the banner of the team to the default. If the team name is not provided, uses the sender's team.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java new file mode 100644 index 0000000..5226fee --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java @@ -0,0 +1,82 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.gui.teams.TeamsSelectorGUI; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "gui", noPermission = true, inheritPermission = false) +public class UHTeamGUICommand extends AbstractCommand +{ + public UHTeamGUICommand(UHCReloaded plugin) {} + + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER, this); + } + + Gui.open((Player) sender, new TeamsSelectorGUI()); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team gui {ci}: opens a GUI to join and manage the teams.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java new file mode 100644 index 0000000..6586657 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java @@ -0,0 +1,192 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * This class is used for both /uh team join and /join commands. + * + * @see {@link eu.carrade.amaury.UHCReloaded.commands.commands.JoinCommand}. + */ +@Command (name = "join") +public class UHTeamJoinCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamJoinCommand(UHCReloaded plugin) + { + p = plugin; + } + + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(final CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + + UHTeam team; + + String targetName = ""; + Boolean self = null; + + // /... join ? + team = p.getTeamManager().getTeam(UHUtils.getStringFromCommandArguments(args, 0)); + if (team != null) + { + if (sender instanceof Player) + { + targetName = sender.getName(); + self = true; + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + } + + // /... join ? + else if (args.length >= 2) + { + team = p.getTeamManager().getTeam(UHUtils.getStringFromCommandArguments(args, 1)); + if (team != null) + { + targetName = args[0]; + self = false; + } + } + + if (team == null) + { + sender.sendMessage(I.t("{ce}This team does not exists.")); + } + else if (sender.hasPermission("uh.team.join") + || (self && sender.hasPermission("uh.player.join.self")) + || (!self && sender.hasPermission("uh.player.join.others"))) + { + final UHTeam finalTeam = team; + OfflinePlayersLoader.loadPlayer(targetName, new Callback() + { + @Override + public void call(OfflinePlayer player) + { + if (player == null) + { + sender.sendMessage(I.t("{ce}Unable to retrieve the player {0}.")); + + if (!Bukkit.getOnlineMode()) + sender.sendMessage(I.t("{ce}In offline mode, you cannot add players if they never came to this server.")); + + return; + } + + finalTeam.addPlayer(player); + + if (!sender.equals(player)) + { + sender.sendMessage(I.t("{cs}The player {0} was successfully added to the team {1}", player.getName(), finalTeam.getName())); + } + } + }); + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED, this); + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + + if (args.length >= 2) + { + ArrayList teamNames = new ArrayList<>(); + + for (UHTeam team : this.p.getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 1), teamNames, args.length - 2); + } + + else return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team join {ci}: adds a player inside the given team. The name of the team is it color, or the explicit name given.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java new file mode 100644 index 0000000..2e32eef --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java @@ -0,0 +1,145 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "leave") +public class UHTeamLeaveCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamLeaveCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + final OfflinePlayer target; + + if (args.length == 0) + { + if (sender instanceof Player) + { + target = (OfflinePlayer) sender; + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER); + } + } + + // /uh team leave + else + { + target = OfflinePlayersLoader.getOfflinePlayer(args[0]); + } + + + if (target == null) + { + sender.sendMessage(I.t("{ce}The player {0} is disconnected and never logged in before!", args[0])); // args.length >= 1 here. + } + + else + { + + // Permissions check + if (sender.hasPermission("uh.team.leave") + || (target.equals(sender) && sender.hasPermission("uh.player.leave.self")) + || (!target.equals(sender) && sender.hasPermission("uh.player.leave.others"))) + { + + + p.getTeamManager().removePlayerFromTeam(target); + + if (!target.equals(sender)) + { + sender.sendMessage(I.t("{cs}The player {0} was successfully removed from his team.", target.getName())); + } + + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED); + } + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team leave {ci}: removes a player from his team.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java new file mode 100644 index 0000000..844508e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java @@ -0,0 +1,122 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "list") +public class UHTeamListCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamListCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (p.getTeamManager().getTeams().size() == 0) + { + sender.sendMessage(I.t("{ce}There isn't any team to show.")); + return; + } + + for (final UHTeam team : p.getTeamManager().getTeams()) + { + sender.sendMessage(I.tn("{0} ({1} player)", "{0} ({1} players)", team.getSize(), team.getDisplayName(), team.getSize())); + for (final OfflinePlayer player : team.getPlayers()) + { + String bullet; + if (player.isOnline()) + { + /// Online dot in /uh team list + bullet = I.t("{green} • "); + } + else + { + /// Offline dot in /uh team list + bullet = I.t("{red} • "); + } + + /// Player name after the online status dot in /uh teams list + sender.sendMessage(bullet + I.tc("teams_list", "{0}", player.getName())); + } + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team list {ci}: lists the teams and their players.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java new file mode 100644 index 0000000..6f53cb9 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java @@ -0,0 +1,121 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "remove") +public class UHTeamRemoveCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamRemoveCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length >= 1) + { // /uh team remove + String name = UHUtils.getStringFromCommandArguments(args, 0); + if (!p.getTeamManager().removeTeam(name)) + { + sender.sendMessage(I.t("{ce}This team does not exists.")); + } + else + { + sender.sendMessage(I.t("{cs}Team {0} deleted.", name)); + } + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + ArrayList teamNames = new ArrayList<>(); + + for (UHTeam team : this.p.getTeamManager().getTeams()) + { + teamNames.add(team.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team remove {ci}: removes a team")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java new file mode 100644 index 0000000..fbc1d7d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java @@ -0,0 +1,95 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "reset") +public class UHTeamResetCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTeamResetCommand(UHCReloaded plugin) + { + p = plugin; + } + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + p.getTeamManager().reset(); + sender.sendMessage(I.t("{cs}All teams where removed.")); + } + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team reset {ci}: removes all teams.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java new file mode 100644 index 0000000..fc18e0b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java @@ -0,0 +1,125 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.team; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; + + +@Command (name = "spy") +public class UHTeamSpyCommand extends AbstractCommand +{ + private final UHCReloaded p; + + public UHTeamSpyCommand(UHCReloaded plugin) + { + p = plugin; + } + + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + Player target; + + if (args.length >= 1) + { + if (sender.hasPermission("uh.team.spy.others")) + { + target = Bukkit.getPlayer(args[0]); + if (target == null) + { + sender.sendMessage(I.t("{ce}Cannot toggle the spy mode of {0} because he/she is offline.", args[0])); + return; + } + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED, this); + } + } + else + { + if (!(sender instanceof Player)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.ONLY_AS_A_PLAYER, this); + } + + target = (Player) sender; + } + + + String message; + + if (p.getTeamChatManager().isGlobalSpy(target.getUniqueId())) + { + p.getTeamChatManager().removeGlobalSpy(target.getUniqueId()); + message = I.t("{cs}Spy mode {darkred}disabled{cs} for {0}.", target.getName()); + } + else + { + p.getTeamChatManager().addGlobalSpy(target.getUniqueId()); + message = I.t("{cs}Spy mode {darkgreen}enabled{cs} for {0}.", target.getName()); + } + + target.sendMessage(message); + if (!sender.equals(target)) + sender.sendMessage(message); + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to receive all the team chats (read-only). Execute again to stop.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java new file mode 100644 index 0000000..20e4c6d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java @@ -0,0 +1,113 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + + +/** + * Usage: /uh timers add + */ +@Command (name = "add") +public class UHTimersAddCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersAddCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + + if (args.length < 2) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + else + { + try + { + Integer duration = UHUtils.string2Time(args[0]); + String timerName = UHUtils.getStringFromCommandArguments(args, 1); + + if (p.getTimerManager().getTimer(timerName) != null) + { + sender.sendMessage(I.t("{ce}A timer called {0}{ce} already exists; please choose another name.", timerName)); + return; + } + + UHTimer timer = new UHTimer(timerName); + timer.setDuration(duration); + + p.getTimerManager().registerTimer(timer); + sender.sendMessage(I.t("{cs}The timer {0}{cs} (duration {1}) has been registered.", timer.getDisplayName(), args[0])); + + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or hh:mm:ss.")); + } + } + } + + @Override + public List tabComplete(CommandSender sender, String[] args) + { + return null; + } + + @Override + public List help(CommandSender sender) + { + return null; + } + + @Override + public List onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers add {ci}: adds a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java new file mode 100644 index 0000000..27f7a4f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java @@ -0,0 +1,103 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "display") +public class UHTimersDisplayCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersDisplayCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + sender.sendMessage(I.t("{cs}The timer {0}{cs} is now displayed.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard. Automatic when a timer is started.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java new file mode 100644 index 0000000..b047eb5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java @@ -0,0 +1,103 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "hide") +public class UHTimersHideCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersHideCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + + UHTimer timer = p.getTimerManager().getTimer(timerName); + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + sender.sendMessage(I.t("{cs}The timer {0}{cs} is now hidden.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. Don't stops the timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java new file mode 100644 index 0000000..331c1ab --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java @@ -0,0 +1,125 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + + +@Command (name = "list") +public class UHTimersListCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersListCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + Collection<UHTimer> timers = p.getTimerManager().getTimers(); + + sender.sendMessage(I.tn("{ci}{0} timer is registered.", "{ci}{0} timers are registered.", timers.size())); + + for (UHTimer timer : timers) + { + if (timer.isRunning()) + { + if (timer.isPaused()) + { + sender.sendMessage(I.tn("{yellow} • {{ci}{0}{ci} - total {1} second - {2}", "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}", + timer.getDuration(), + timer.getDisplayName(), + timer.getDuration(), + timer.toString() + )); + } + else + { + sender.sendMessage(I.tn("{green} • {ci}{0}{ci} - total {1} second - {2}", "{green} • {ci}{0}{ci} - total {1} seconds - {2}", + timer.getDuration(), + timer.getDisplayName(), + timer.getDuration(), + timer.toString() + )); + } + } + else + { + sender.sendMessage(I.tn("{red} • {ci}{0}{ci} - total {1} second", "{red} • {ci}{0}{ci} - total {1} seconds", + timer.getDuration(), + timer.getDisplayName(), + timer.getDuration() + )); + } + } + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers list {ci}: lists the registered timers.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java new file mode 100644 index 0000000..d6ac577 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java @@ -0,0 +1,104 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "pause") +public class UHTimersPauseCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersPauseCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + timer.setPaused(true); + sender.sendMessage(I.t("{cs}The timer {0}{cs} is now paused.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers pause <title ...> {ci}: pauses a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java new file mode 100644 index 0000000..0b4b45e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java @@ -0,0 +1,106 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "remove") +public class UHTimersRemoveCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersRemoveCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + p.getTimerManager().unregisterTimer(timer); + timer.stop(); + + sender.sendMessage(I.t("{cs}The timer {0}{cs} has been deleted.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers remove <title ...> {ci}: deletes a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java new file mode 100644 index 0000000..85239c4 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java @@ -0,0 +1,104 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "resume") +public class UHTimersResumeCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersResumeCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + timer.setPaused(false); + sender.sendMessage(I.t("{cs}The timer {0}{cs} was resumed.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers resume <title ...> {ci}: resumes a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java new file mode 100644 index 0000000..5bce4a5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java @@ -0,0 +1,126 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * Usage: /uh timers set <duration> <name ...> + */ +@Command (name = "set") +public class UHTimersSetCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersSetCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + + if (args.length < 2) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + else + { + try + { + Integer duration = UHUtils.string2Time(args[0]); + String timerName = UHUtils.getStringFromCommandArguments(args, 1); + + UHTimer timer = p.getTimerManager().getTimer(timerName); + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + timer.setDuration(duration); + sender.sendMessage(I.t("{cs}The duration of the timer {0}{cs} is now {1}.", timer.getDisplayName(), args[0])); + + } + catch (IllegalArgumentException e) + { + sender.sendMessage(I.t("{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or hh:mm:ss.")); + } + } + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + + if (args.length >= 2) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 1), suggestions, args.length - 2); + } + + else return null; + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java new file mode 100644 index 0000000..e169a14 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java @@ -0,0 +1,109 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "start") +public class UHTimersStartCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersStartCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + if (timer.isRunning()) + { + timer.stop(); + } + + timer.start(); + sender.sendMessage(I.t("{cs}The timer {0}{cs} was started.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers start <title ...> {ci}: starts a timer.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java new file mode 100644 index 0000000..c4d629d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java @@ -0,0 +1,104 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.commands.uh.timers; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@Command (name = "stop") +public class UHTimersStopCommand extends AbstractCommand +{ + private UHCReloaded p; + + public UHTimersStopCommand(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.BAD_USE, this); + } + + String timerName = UHUtils.getStringFromCommandArguments(args, 0); + UHTimer timer = p.getTimerManager().getTimer(timerName); + + if (timer == null) + { + sender.sendMessage(I.t("{ce}This timer is not registered.")); + return; + } + + timer.stop(); + sender.sendMessage(I.t("{cs}The timer {0}{cs} was stopped.", timer.getDisplayName())); + } + + @Override + public List<String> tabComplete(CommandSender sender, String[] args) + { + List<String> suggestions = new ArrayList<>(); + + for (UHTimer timer : p.getTimerManager().getTimers()) + { + suggestions.add(timer.getName()); + } + + return CommandUtils.getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), suggestions, args.length - 1); + } + + @Override + public List<String> help(CommandSender sender) + { + return null; + } + + @Override + public List<String> onListHelp(CommandSender sender) + { + return Collections.singletonList(I.t("{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be removed from the scoreboard.")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommand.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommand.java new file mode 100644 index 0000000..9c11b97 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommand.java @@ -0,0 +1,409 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.core; + +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import org.bukkit.command.CommandSender; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +/** + * Represents a command with subcommands (or not). + * + * <p> + * Add the subcommands with the {@link #registerSubCommand} method in the constructor.<br /> + * A subcommand is simply an {@link AbstractCommand} object. + * </p> + * + * @version 1.0 + * @author Amaury Carrade + */ +public abstract class AbstractCommand +{ + /** + * Stores the sub-commands of this complex command. + * + * <p>name → command.</p> + */ + private Map<String, AbstractCommand> subcommands = new LinkedHashMap<>(); + + /** + * Stores the permissions of the sub-commands. + * + * <p>name → permission.</p> + */ + private Map<String, String> permissions = new LinkedHashMap<>(); + + /** + * Stores the sub-commands per category. + * + * <p>name → category.</p> + */ + private Map<String, String> subcommandsCategories = new LinkedHashMap<>(); + + /** + * The parent command. + * + * <p> + * Example, for {@code /cmd foo bar}, the parent command of {@code bar} + * is the command {@code foo}. + * </p> + * <p> + * Without parent (root command), {@code null}. + * </p> + */ + private AbstractCommand parent = null; + + + /** + * Runs the command. + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + * + * @throws eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException If the command cannot be executed. + */ + public abstract void run(CommandSender sender, String[] args) throws CannotExecuteCommandException; + + /** + * Tab-completes this command. + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + public abstract List<String> tabComplete(CommandSender sender, String[] args); + + /** + * Returns the help of this command. + * + * <p> + * These lines will only be displayed if the {@link CannotExecuteCommandException} is + * caught by the command executor, with the reasons {@code BAD_USE} or {@code NEED_DOC}. + * </p> + * <p> + * If this returns null, fallsback to {@link #onListHelp}. + * </p> + * + * + * @param sender The sender. + * + * @return The help. One line per entry in the list. + */ + public abstract List<String> help(CommandSender sender); + + /** + * Returns the help displayed in the list of the commands, in the help + * of the parent command. + * + * <p> + * You should return one single line here, except for special cases. + * </p> + * + * @param sender The sender. + * + * @return The help. One line displayed per entry in the list. + */ + public abstract List<String> onListHelp(CommandSender sender); + + /** + * Returns the title of the category of the command. + * + * <p> + * This category will be displayed as a title in the commands' list.<br /> + * If the value defined is empty, or null, or the method not overwritten, + * the command will be not categorized. + * </p> + * + * <p> + * This category must be unique in the sub-commands of a command. + * </p> + * + * <p> + * You should either use a category for all subcommands of a command, either no categories + * at all for these commands. Else, the non-categorized commands will be displayed somewhere, + * and this place may vary. + * </p> + */ + public String getCategory() + { + return null; + } + + + /** + * Sets the parent command of this command. Can be set only one time. + * + * @param parent The parent. + * + * @throws IllegalArgumentException If the parent command is already set. + */ + public void setParent(AbstractCommand parent) + { + if (this.parent != null) + { + throw new IllegalArgumentException("The parent command is already set!"); + } + + this.parent = parent; + } + + /** + * Returns the parent command. + * + * @return The parent; {@code null} if this command is a root one. + */ + public AbstractCommand getParent() + { + return parent; + } + + + /** + * Registers a subcommand of this command. + * + * @param command The command to register. + * + * @throws IllegalArgumentException If the command object don't have the {@link eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command} annotation. + */ + public void registerSubCommand(AbstractCommand command) + { + Command commandAnnotation = command.getClass().getAnnotation(Command.class); + + if (commandAnnotation == null) + { + throw new IllegalArgumentException("Cannot register a command without @Command annotation. Class: " + command.getClass().getCanonicalName() + "."); + } + + command.setParent(this); + + String name = commandAnnotation.name(); + String permission = commandAnnotation.permission(); + + if (permission == null && !commandAnnotation.useParentPermission()) + { + permission = commandAnnotation.name(); + } + + if (permission != null && permission.isEmpty() || commandAnnotation.noPermission()) + { + permission = null; + } + + if (commandAnnotation.inheritPermission() || commandAnnotation.useParentPermission()) + { + + AbstractCommand parent = this; + if (commandAnnotation.useParentPermission()) + { + // We starts at the parent to get the parent's permission. + parent = this.getParent(); + } + + while (parent != null) + { + // The parent will always have the @Command annotation, because it is always + // added in this method and the presence of the annotation is checked. + Command parentAnnotation = parent.getClass().getAnnotation(Command.class); + if (parentAnnotation.permission() != null && !parentAnnotation.permission().isEmpty()) + { + permission = parentAnnotation.permission(); + if (permission != null && !permission.isEmpty()) + { + permission += "." + permission; + } + } + parent = parent.getParent(); + } + } + + // Let's save these permissions and executors. + subcommands.put(name, command); + permissions.put(name, permission); + + // Categories + if (command.getCategory() != null && !command.getCategory().isEmpty()) + { + subcommandsCategories.put(name, command.getCategory()); + } + } + + /** + * Routes the command, to a sub command, with a fallback to the + * {@link #run} method of this command if no subcommand matches + * or if there isn't any argument passed to this command. + * + * <p> + * Internal use. Do not override this. Ignore this. + * </p> + * + * @param sender The sender of the command. + * @param args The arguments passed to the command. + */ + public void routeCommand(CommandSender sender, String[] args) throws CannotExecuteCommandException + { + if (args.length == 0) + { + run(sender, new String[0]); + } + else + { + AbstractCommand cmd = subcommands.get(args[0]); + if (cmd != null) + { + // Allowed? + String permission = permissions.get(args[0]); + if (permission == null || sender.hasPermission(permission)) + { + cmd.routeCommand(sender, CommandUtils.getSubcommandArguments(args)); + } + else + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED); + } + } + else + { + run(sender, args); + } + } + } + + /** + * Routes to the autocompleter of this command. + * + * <p> + * Internal use. Do not override this. Ignore this. + * </p> + * + * @param sender The sender. + * @param args The arguments passed to the command. + * + * @return A list of suggestions. + */ + public List<String> routeTabComplete(CommandSender sender, String[] args) + { + // Autocompletion for this command + if (args.length == 1) + { + List<String> suggestions = new LinkedList<>(); + + for (String command : subcommands.keySet()) + { + String permission = permissions.get(command); + if (permission == null || sender.hasPermission(permission)) + { + suggestions.add(command); + } + } + + suggestions = CommandUtils.getAutocompleteSuggestions(args[0], suggestions); + + List<String> suggestionsFromThisCommand = tabComplete(sender, args); + if (suggestionsFromThisCommand != null) + { + suggestions.addAll(suggestionsFromThisCommand); + } + + return suggestions; + } + + // Autocompletion for a subcommand + else + { + AbstractCommand subcommand = subcommands.get(args[0]); + if (subcommand != null) + { + return subcommand.routeTabComplete(sender, CommandUtils.getSubcommandArguments(args)); + } + else + { + return tabComplete(sender, args); + } + } + } + + /** + * Returns the subcommands. + * + * <p> + * Map: name of the command → UHCommand object. + * </p> + * + * @return the subcommands. + */ + public Map<String, AbstractCommand> getSubcommands() + { + return subcommands; + } + + /** + * Returns the permissions of the subcommands. + * + * <p> + * Map: name of the command → raw permission of this command. + * </p> + * + * @return the permissions of the subcommands. + */ + public Map<String, String> getSubcommandsPermissions() + { + return permissions; + } + + /** + * Returns true if this command has subcommands. + */ + public boolean hasSubCommands() + { + return subcommands.size() > 0; + } + + /** + * Returns the categories of the subcommands. + * + * <p> + * Map: name of the command → title of the category of this command. + * </p> + */ + public Map<String, String> getSubcommandsCategories() + { + return subcommandsCategories; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java new file mode 100644 index 0000000..dbb2861 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java @@ -0,0 +1,288 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.core; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.commands.core.exceptions.CannotExecuteCommandException; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +/** + * The base of every command executor. + * + * <p> + * The command executors needs to extend this class and to register the commands in the constructor + * with the method {@link #registerCommand}. + * </p> + * + * @version 1.0 + * @author Amaury Carrade + */ +public abstract class AbstractCommandExecutor implements TabExecutor +{ + private UHCReloaded p; + + /** + * Stores the main commands, i.e. the commands registered in the {@code plugin.yml} file. + */ + private Map<String, AbstractCommand> mainCommands = new LinkedHashMap<>(); + + /** + * Stores the base permissions of these commands. + */ + private Map<String, String> mainCommandsPermissions = new LinkedHashMap<>(); + + + public AbstractCommandExecutor(UHCReloaded plugin) + { + p = plugin; + } + + + /** + * Registers a main, root command. This command must be in the {@code plugin.yml}, or + * it will never be called. + * + * @param command The command. + * + * @throws IllegalArgumentException If the command class doesn't have the @Command + * annotation. + */ + public void registerCommand(AbstractCommand command) + { + Command commandAnnotation = command.getClass().getAnnotation(Command.class); + if (commandAnnotation == null) + { + throw new IllegalArgumentException("Cannot register a command without @Command annotation. Class: " + command.getClass().getCanonicalName() + "."); + } + + mainCommands.put(commandAnnotation.name(), command); + + String permission = commandAnnotation.permission(); + + if (commandAnnotation.noPermission()) + { + permission = null; + } + else if (permission != null && permission.isEmpty()) + { + if (commandAnnotation.useParentPermission()) + { + permission = null; + } + else + { + permission = commandAnnotation.name(); + } + } + + mainCommandsPermissions.put(commandAnnotation.name(), permission); + } + + + /** + * Displays the help of a command. + * + * <p> + * If the command is a complex command, this will display the help of the complex command, + * first line excepted, ath then the short help of all sub-commands.<br /> + * Else, this will display the full help for the command. + * </p> + * + * @param sender The sender. + * @param command The command. + * @param isAnError {@code true} if this is displayed due to an error. + */ + public void displayHelp(CommandSender sender, AbstractCommand command, boolean isAnError) + { + if (command.hasSubCommands()) + { + List<String> help = new LinkedList<>(); + + // Root help + List<String> rootHelp = command.help(sender); + if (rootHelp != null) + { + help.addAll(rootHelp); + } + + // Then, the help of the sub-commands sorted by category. + // We first organize the commands per-category. + Map<String, LinkedList<String>> helpPerCategory = new LinkedHashMap<>(); + + for (Map.Entry<String, AbstractCommand> subCommand : command.getSubcommands().entrySet()) + { + List<String> subHelp = subCommand.getValue().onListHelp(sender); + String permission = command.getSubcommandsPermissions().get(subCommand.getKey()); + String category = command.getSubcommandsCategories().get(subCommand.getKey()); + + if (category == null) category = ""; + + if (subHelp != null && subHelp.size() > 0 && (permission == null || sender.hasPermission(permission))) + { + + LinkedList<String> helpForThisCategory = helpPerCategory.get(category); + if (helpForThisCategory != null) + { + helpForThisCategory.addAll(subHelp); + } + else + { + helpForThisCategory = new LinkedList<>(); + helpForThisCategory.addAll(subHelp); + helpPerCategory.put(category, helpForThisCategory); + } + } + } + + // After, we add to the help to display these commands, with the titles of the + // categories. + for (Map.Entry<String, LinkedList<String>> category : helpPerCategory.entrySet()) + { + help.add(category.getKey()); + help.addAll(category.getValue()); + } + + displayHelp(sender, help, isAnError); + } + else + { + List<String> help = command.help(sender); + if (help == null) help = command.onListHelp(sender); + + displayHelp(sender, help, isAnError); + } + } + + /** + * Displays the help of a command. + * + * @param sender The sender; this user will receive the help. + * @param help The help to display (one line per entry; raw display). + * @param isAnError {@code true} if this is displayed due to an error. + */ + public void displayHelp(CommandSender sender, List<String> help, boolean isAnError) + { + CommandUtils.displaySeparator(sender); + + if (!isAnError) + { + sender.sendMessage(I.t("{yellow}{0} - version {1}", p.getDescription().getDescription(), p.getDescription().getVersion())); + sender.sendMessage(I.t("{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed ...>{ci}.")); + } + + if (help != null) + { + for (String line : help) + { + if (line != null && !line.isEmpty()) + sender.sendMessage(line); + } + } + + CommandUtils.displaySeparator(sender); + + if (isAnError) + { + sender.sendMessage(I.t("{ce}{bold}You cannot execute this command this way.")); + sender.sendMessage(I.t("{ce}The help is displayed above.")); + CommandUtils.displaySeparator(sender); + } + } + + + @Override + public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String alias, String[] args) + { + AbstractCommand abstractCommand = mainCommands.get(command.getName()); + if (abstractCommand == null) + { + return false; + } + + try + { + String permission = mainCommandsPermissions.get(command.getName()); + if (permission != null && !sender.hasPermission(permission)) + { + throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED); + } + + abstractCommand.routeCommand(sender, args); + + } + catch (CannotExecuteCommandException e) + { + switch (e.getReason()) + { + case NOT_ALLOWED: + sender.sendMessage(I.t("{ce}You are not allowed to execute this command.")); + break; + + case ONLY_AS_A_PLAYER: + sender.sendMessage(I.t("{ce}This can only be executed as a player.")); + break; + + case BAD_USE: + case NEED_DOC: + displayHelp(sender, e.getOrigin() != null ? e.getOrigin() : abstractCommand, e.getReason() == CannotExecuteCommandException.Reason.BAD_USE); + break; + + case UNKNOWN: + break; + } + } + + return true; + } + + @Override + public List<String> onTabComplete(CommandSender sender, org.bukkit.command.Command command, String alias, String[] args) + { + AbstractCommand abstractCommand = mainCommands.get(command.getName()); + return abstractCommand.routeTabComplete(sender, args); + } + + public Map<String, AbstractCommand> getMainCommands() + { + return mainCommands; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/annotations/Command.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/annotations/Command.java new file mode 100644 index 0000000..f726f3c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/annotations/Command.java @@ -0,0 +1,107 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.commands.core.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * This annotation needs to be applied to every command class. It is used to define the + * name and the permission of the command. + * + * @version 1.0 + * @author Amaury Carrade + */ +@Retention (RetentionPolicy.RUNTIME) +@Target (ElementType.TYPE) +public @interface Command +{ + + /** + * The name of the command, needed to type in the console/chat to execute + * the (sub-)command. + */ + public String name(); + + /** + * The permission needed to execute this command. + * + * <p> + * Please note that with the current version of this API, the user will need to have the right to + * access the parent commands, to access this command.<br /> + * This situation may evolve in the future. + * </p> + * <p> + * If the {@code inheritPermission} option is unset or set to {@code true}, + * this permission is <strong>concatened to the parent permissions</strong>.<br /> + * As example, if the permission is set to {@code sb}, and if the parent command + * have the permission {@code cmd.norris}, the real permission of the command will + * be {@code cmd.norris.sb}. + * </p> + * <p> + * If this is left empty, or not set, the permission will be the name of the command, excepted + * if {@link #useParentPermission} is set to true. + * </p> + */ + public String permission() default ""; + + /** + * If this is set to {@code false}, the permission will be interpreted <em>as-is</em>, + * without concatenation with the permissions of the parent commands. + * + * <p> + * You should not set this to {@code false} if the command have sub-commands with this + * set to {@code true}, or weired behavior may happens. + * </p> + */ + public boolean inheritPermission() default true; + + /** + * If this is set to {@code true}, the permission of the parent command will be used. + * + * <p> + * If the parent command is {@code null} (i.e. this command is a root one), the command will be + * accessible to everyone. + * </p> + */ + public boolean useParentPermission() default false; + + /** + * If this is set to true, no permissions check will be done when someone + * executes this command. + */ + public boolean noPermission() default false; +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/exceptions/CannotExecuteCommandException.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/exceptions/CannotExecuteCommandException.java new file mode 100644 index 0000000..b755752 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/exceptions/CannotExecuteCommandException.java @@ -0,0 +1,102 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.core.exceptions; + +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; + + +/** + * This exception is fired when a command cannot be executed, for whatever reason. + * + * @version 1.0 + * @author Amaury Carrade + */ +public class CannotExecuteCommandException extends Exception +{ + + public enum Reason + { + /** + * Use this if the player is not allowed to execute the command. + */ + NOT_ALLOWED, + + /** + * Use this if the command can only be executed as a player, and + * the sender is not a player. + */ + ONLY_AS_A_PLAYER, + + /** + * Use this if the sender used the command badly. + * + * <p> + * This will display the documentation and an error message. + * </p> + */ + BAD_USE, + + /** + * Use this to have the documentation of the command displayed. + */ + NEED_DOC, + + /** + * Use this in other cases. + */ + UNKNOWN + } + + private Reason reason; + private AbstractCommand origin; + + public CannotExecuteCommandException(Reason reason, AbstractCommand origin) + { + this.reason = reason; + this.origin = origin; + } + + public CannotExecuteCommandException(Reason reason) + { + this(reason, null); + } + + public Reason getReason() + { + return reason; + } + + public AbstractCommand getOrigin() + { + return origin; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/utils/CommandUtils.java b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/utils/CommandUtils.java new file mode 100644 index 0000000..a2c0478 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/utils/CommandUtils.java @@ -0,0 +1,237 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands.core.utils; + +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class CommandUtils +{ + + /** + * Returns {@code true} if the sender is allowed to execute the given command. + * + * <p> + * Use that only if you have an isolated UHCommand object. Not if you have a direct access to + * the parent command, or if you know the command is a root command. + * </p> + * + * @param sender The sender. + * @param command The command. + * + * @return {@code true} if the sender is allowed to execute the command. + */ + public static boolean isAllowed(CommandSender sender, AbstractCommand command) + { + if (command.getParent() == null) + { // root command + Command commandAnnotation = command.getClass().getAnnotation(Command.class); + if (commandAnnotation != null) + { + if (commandAnnotation.permission() == null) + { + return true; + } + else if (commandAnnotation.permission().isEmpty()) + { + return sender.hasPermission(commandAnnotation.name()); + } + else + { + return sender.hasPermission(commandAnnotation.permission()); + } + } + } + else + { + return sender.hasPermission(command.getParent().getSubcommandsPermissions().get(command.getClass().getAnnotation(Command.class).name())); + } + + return false; // should never happens. + } + + /** + * Returns the args without the first item. + * + * @param args The arguments sent to the parent command. + * @return The arguments to send to the child command. + */ + public static String[] getSubcommandArguments(String[] args) + { + if (args.length <= 1) + { + return new String[0]; + } + + return Arrays.copyOfRange(args, 1, args.length); + } + + + /** + * Returns the tags in the arguments, following the format "tagname:value". + * + * <p> + * If a tag is defined multiple times, the value used is the last one. + * </p> + * <p> + * Invalid tags (other format that « key:value ») are ignored. + * </p> + * + * @param args The args. + * @param defaults The defaults values. The values defined here will always be in the returned map, + * with the same value if the key is not in the arguments. + * {@code null} if no default values are needed. + * + * @return A map tagname -> value. + */ + public static Map<String, String> getTagsInArgs(String[] args, Map<String, String> defaults) + { + Map<String, String> tagsCollected; + + if (defaults != null) + { + tagsCollected = new HashMap<>(defaults); + } + else + { + tagsCollected = new HashMap<>(); + } + + for (String arg : args) + { + String[] argSpilt = arg.split(":"); + if (argSpilt.length >= 2) // valid + { + String key = argSpilt[0]; + String value = StringUtils.join(Arrays.copyOfRange(argSpilt, 1, argSpilt.length), ":"); + + tagsCollected.put(key, value); + } + } + + return tagsCollected; + } + + + /** + * Returns a list of autocompletion suggestions based on what the user typed and on a list of + * available commands. + * + * @param typed What the user typed. This string needs to include <em>all</em> the words typed. + * @param suggestionsList The list of the suggestions. + * @param numberOfWordsToIgnore If non-zero, this number of words will be ignored at the beginning of the string. This is used to handle multiple-words autocompletion. + * + * @return The list of matching suggestions. + */ + public static List<String> getAutocompleteSuggestions(String typed, List<String> suggestionsList, int numberOfWordsToIgnore) + { + List<String> list = new ArrayList<String>(); + + // For each suggestion: + // - if there isn't any world to ignore, we just compare them; + // - else, we removes the correct number of words at the beginning of the string; + // then, if the raw suggestion matches the typed text, we adds to the suggestion list + // the filtered suggestion, because the Bukkit's autocompleter works on a “per-word” basis. + + for (String rawSuggestion : suggestionsList) + { + String suggestion; + + if (numberOfWordsToIgnore == 0) + { + suggestion = rawSuggestion; + } + else + { + // Not the primary use, but, hey! It works. + suggestion = UHUtils.getStringFromCommandArguments(rawSuggestion.split(" "), numberOfWordsToIgnore); + } + + if (rawSuggestion.toLowerCase().startsWith(typed.toLowerCase())) + { + list.add(suggestion); + } + } + + Collections.sort(list, Collator.getInstance()); + + return list; + } + + /** + * Returns a list of autocompletion suggestions based on what the user typed and on a list of + * available commands. + * + * @param typed What the user typed. + * @param suggestionsList The list of the suggestions. + * + * @return The list of matching suggestions. + */ + public static List<String> getAutocompleteSuggestions(String typed, List<String> suggestionsList) + { + return getAutocompleteSuggestions(typed, suggestionsList, 0); + } + + + /** + * Displays a separator around the output of the commands. + * + * <p> + * To be called before and after the output (prints a line only). + * </p> + * + * @param sender The line will be displayed for this sender. + */ + public static void displaySeparator(CommandSender sender) + { + if (!(sender instanceof Player)) + { + return; + } + + sender.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/EpisodeChangedCause.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/EpisodeChangedCause.java new file mode 100644 index 0000000..70bb4f4 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/EpisodeChangedCause.java @@ -0,0 +1,47 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +public enum EpisodeChangedCause +{ + /** + * The episode changed because the previous episode was finished. + */ + FINISHED, + + /** + * The episode changed because the previous episode was shifted by someone using + * the {@code /uh shift} command. + */ + SHIFTED +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerEndsEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerEndsEvent.java new file mode 100644 index 0000000..c170d2c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerEndsEvent.java @@ -0,0 +1,113 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * This event is fired when a timer ends. + * <p> + * It is fired before all the values of the timer are reset. + */ +public final class TimerEndsEvent extends Event +{ + private UHTimer timer; + private Boolean timerWasUp = false; + private Boolean restart = false; + + + public TimerEndsEvent(UHTimer timer, Boolean timerUp) + { + this.timer = timer; + + this.timerWasUp = timerUp; + } + + /** + * Returns the timer. + * + * @return the timer. + */ + public UHTimer getTimer() + { + return timer; + } + + /** + * Returns true if the timer was stopped because it was up. + * + * @return true if the timer was stopped because it was up. + */ + public boolean wasTimerUp() + { + return timerWasUp; + } + + /** + * If true, the timer will be restarted. + * + * @param restart true if the timer needs to be restarted. + */ + public void setRestart(boolean restart) + { + this.restart = restart; + } + + /** + * Return true if the timer will be restarted. + * + * @return {@code true} if the timer needs to be restarted. + */ + public boolean getRestart() + { + return this.restart; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerStartsEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerStartsEvent.java new file mode 100644 index 0000000..2476221 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/TimerStartsEvent.java @@ -0,0 +1,77 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * This event is fired when a timer ends. + * + * @author Amaury Carrade + */ +public final class TimerStartsEvent extends Event +{ + private UHTimer timer; + + public TimerStartsEvent(UHTimer timer) + { + this.timer = timer; + } + + /** + * Returns the timer. + * + * @return + */ + public UHTimer getTimer() + { + return timer; + } + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHEpisodeChangedEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHEpisodeChangedEvent.java new file mode 100644 index 0000000..94a5473 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHEpisodeChangedEvent.java @@ -0,0 +1,102 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * Called when an episode changes. + */ +public class UHEpisodeChangedEvent extends Event +{ + private int newEpisode; + private EpisodeChangedCause cause; + private String shifter; + + public UHEpisodeChangedEvent(int newEpisode, EpisodeChangedCause cause, String shifter) + { + this.newEpisode = newEpisode; + this.cause = cause; + this.shifter = shifter; + } + + /** + * Returns the new episode. + * + * @return The new episode. + */ + public int getNewEpisode() + { + return newEpisode; + } + + /** + * Why the episode changed? + * + * @return The cause. + * + * @see EpisodeChangedCause + */ + public EpisodeChangedCause getCause() + { + return cause; + } + + /** + * Returns the name of the shifter (the one that executed the /uh shift command, or "" if + * the episode was shifted because the previous one was finished). + * + * @return The shifter. + */ + public String getShifter() + { + return shifter; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameEndsEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameEndsEvent.java new file mode 100644 index 0000000..1988d69 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameEndsEvent.java @@ -0,0 +1,93 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +public class UHGameEndsEvent extends Event implements Cancellable +{ + private UHTeam winner; + private boolean cancelled = false; + + public UHGameEndsEvent(UHTeam winner) + { + this.winner = winner; + } + + /** + * Returns the last team alive. + * + * @return The team. + */ + public UHTeam getWinnerTeam() + { + return winner; + } + + + @Override + public boolean isCancelled() + { + return cancelled; + } + + /** + * Cancels the game ends. If cancelled, the end message / effects will not be broadcasted. + * + * @param cancelled {@code true} to cancel. + */ + @Override + public void setCancelled(boolean cancelled) + { + this.cancelled = cancelled; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameStartsEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameStartsEvent.java new file mode 100644 index 0000000..2592d7e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHGameStartsEvent.java @@ -0,0 +1,56 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * This event is fired when the UHC game is started. + */ +public class UHGameStartsEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerDeathEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerDeathEvent.java new file mode 100644 index 0000000..f0cbe82 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerDeathEvent.java @@ -0,0 +1,89 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.PlayerDeathEvent; + + +/** + * Fired when a player playing an UHC match is dead. + * <p> + * This event is called before all the action executed on player death (sound, scoreboard updates, etc.). + */ +public class UHPlayerDeathEvent extends Event +{ + private Player player; + private PlayerDeathEvent ev; + + public UHPlayerDeathEvent(Player player, PlayerDeathEvent ev) + { + this.player = player; + this.ev = ev; + } + + /** + * Returns the dead player. + * @return The player. + */ + public Player getPlayer() + { + return player; + } + + /** + * Returns the PlayerDeathEvent under this event. + * @return The PlayerDeathEvent. + */ + public PlayerDeathEvent getPlayerDeathEvent() + { + return ev; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerResurrectedEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerResurrectedEvent.java new file mode 100644 index 0000000..b71bc5b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHPlayerResurrectedEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * Called when a player is resurrected. + * <p> + * This event is called when: + * <ul> + * <li>the command {@code /uh resurrect <player>} is executed, if the target is online;</li> + * <li>the resurrected player logins, else</li> + * </ul> + * (i.e. when the message “the player is resurrected” is broadcasted). + */ +public class UHPlayerResurrectedEvent extends Event +{ + private Player resurrectedPlayer; + + public UHPlayerResurrectedEvent(Player player) + { + this.resurrectedPlayer = player; + } + + /** + * Returns the resurrected player. + * + * @return The player. + */ + public Player getPlayer() + { + return resurrectedPlayer; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHTeamDeathEvent.java b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHTeamDeathEvent.java new file mode 100644 index 0000000..b02ef9e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/events/UHTeamDeathEvent.java @@ -0,0 +1,76 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.events; + +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + + +/** + * Event fired when the last member of a team die. + */ +public class UHTeamDeathEvent extends Event +{ + private UHTeam team; + + public UHTeamDeathEvent(UHTeam team) + { + this.team = team; + } + + /** + * Returns the now-dead team. + * + * @return The team. + */ + public UHTeam getTeam() + { + return team; + } + + + + private static final HandlerList handlers = new HandlerList(); + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/game/Cage.java b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Cage.java new file mode 100644 index 0000000..58db757 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Cage.java @@ -0,0 +1,308 @@ +/* + * Copyright or © or Copr. AmauryCarrade (2015) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.game; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.material.MaterialData; + +import java.util.HashMap; +import java.util.Map; + + +public class Cage +{ + private final Location baseLocation; + + private Material material = Material.BARRIER; + private MaterialData materialData = null; + + private final boolean buildCeiling; + private final boolean visibleWalls; + + private int radius = 1; + private int internalHeight = 3; + + private boolean built = false; + private Map<Location, SimpleBlock> blocksBuilt = new HashMap<>(); + + + /** + * @param baseLocation The cage base location (where a player can be + * teleported to be on the ground). + * @param buildCeiling {@code true} to build the ceiling of the cage. + */ + public Cage(Location baseLocation, boolean buildCeiling, boolean visibleWalls) + { + this.baseLocation = baseLocation; + this.buildCeiling = buildCeiling; + this.visibleWalls = visibleWalls; + } + + /** + * Sets the custom material to use. + * + * @param customMaterial A material. + * @param data The data value (or {@code null}). + */ + public void setCustomMaterial(Material customMaterial, MaterialData data) + { + this.material = customMaterial == null ? Material.BARRIER : customMaterial; + this.materialData = data; + } + + /** + * Sets the custom material to use. + * + * @param customMaterial A material. + * @param data The data value. + */ + public void setCustomMaterial(Material customMaterial, byte data) + { + setCustomMaterial(customMaterial, new MaterialData(this.material, data)); + } + + /** + * Sets the custom material to use. + * + * @param customMaterial A material. + */ + public void setCustomMaterial(Material customMaterial) + { + setCustomMaterial(customMaterial, null); + } + + + /** + * Sets the internal height, i.e. the height of the open space for players + * (the ceiling will be above this height, and the ground under). + * + * @param internalHeight The height. + */ + public void setInternalHeight(int internalHeight) + { + this.internalHeight = internalHeight; + } + + /** + * Sets the square radius of the cage. + * + * With 0, you'll have a cage with one block to walk. With 1, you'll have a + * 3×3 cage. With 2, a 5×5 cage. Etc. + * + * @param radius The radius. + */ + public void setRadius(int radius) + { + this.radius = radius; + } + + /** + * Sets a block (and remembers the old one to clean up things after). + * + * @param location The location + * @param material The block material + */ + private void setBlock(final Location location, final Material material) + { + setBlock(location, material, null); + } + + /** + * Sets a block (and remembers the old one to clean up things after). + * + * @param location The location + * @param material The block material + * @param data The block data value (as byte) + */ + private void setBlock(final Location location, final Material material, final byte data) + { + setBlock(location, material, new MaterialData(material, data)); + } + + /** + * Sets a block (and remembers the old one to clean up things after). + * + * @param location The location + * @param material The block material + * @param data The block data value (as {@link MaterialData}) + */ + private void setBlock(final Location location, final Material material, final MaterialData data) + { + final Block block = location.getBlock(); + + if (!blocksBuilt.containsKey(location)) + blocksBuilt.put(location, new SimpleBlock(block.getType(), block.getState().getData().clone())); + + block.setType(material); + if (data != null) block.setData(data.getData()); + } + + + /** + * Builds the cage. + */ + public void build() + { + if (built) return; + + final int externalRadius = radius + 1; + final int xMin = baseLocation.getBlockX() - externalRadius; + final int xMax = baseLocation.getBlockX() + externalRadius; + final int zMin = baseLocation.getBlockZ() - externalRadius; + final int zMax = baseLocation.getBlockZ() + externalRadius; + + final World world = baseLocation.getWorld(); + + + // Builds the base barrier square under any cage, to support falling blocks and to avoid players falling + // through the blocks when teleported + + for (int x = xMin; x <= xMax; x++) + for (int z = zMin; z <= zMax; z++) + setBlock(new Location(world, x, baseLocation.getBlockY() - 2, z), Material.BARRIER); + + + // Builds the ground + + for (int x = xMin + 1; x <= xMax - 1; x++) + for (int z = zMin + 1; z <= zMax - 1; z++) + setBlock(new Location(world, x, baseLocation.getBlockY() - 1, z), material, materialData); + + + // Builds the walls + + final Material wallsMaterial = visibleWalls ? material : Material.BARRIER; + final MaterialData wallsMaterialData = visibleWalls ? materialData : null; + + for (int x = xMin; x <= xMax; x++) + { + for (int y = baseLocation.getBlockY() - 1; y < baseLocation.getBlockY() + internalHeight; y++) + { + setBlock(new Location(world, x, y, zMin), wallsMaterial, wallsMaterialData); + setBlock(new Location(world, x, y, zMax), wallsMaterial, wallsMaterialData); + } + } + + for (int z = zMin; z <= zMax; z++) + { + for (int y = baseLocation.getBlockY() - 1; y < baseLocation.getBlockY() + internalHeight; y++) + { + setBlock(new Location(world, xMin, y, z), wallsMaterial, wallsMaterialData); + setBlock(new Location(world, xMax, y, z), wallsMaterial, wallsMaterialData); + } + } + + + // Builds the ceiling + + final Material ceilingMaterial = buildCeiling ? material : Material.BARRIER; + final MaterialData ceilingMaterialData = buildCeiling ? materialData : null; + + int xMinCeiling = xMin, xMaxCeiling = xMax, zMinCeiling = zMin, zMaxCeiling = zMax; + + if (buildCeiling && !visibleWalls) + { + xMinCeiling++; + xMaxCeiling--; + zMinCeiling++; + zMaxCeiling--; + } + + for (int x = xMinCeiling; x <= xMaxCeiling; x++) + for (int z = zMinCeiling; z <= zMaxCeiling; z++) + setBlock(new Location(world, x, baseLocation.getBlockY() + internalHeight, z), ceilingMaterial, ceilingMaterialData); + + built = true; + } + + /** + * Destroys the cage. + */ + public void destroy() + { + for (Map.Entry<Location, SimpleBlock> entry : blocksBuilt.entrySet()) + { + final Block block = entry.getKey().getBlock(); + final SimpleBlock originalBlock = entry.getValue(); + + block.setType(originalBlock.material); + + if (originalBlock.data != null) + block.getState().setData(originalBlock.data); + } + + built = false; + } + + + /** + * Cage type, enum used for the configuration + */ + public enum CageType + { + /** + * Cages in stained glass, using the team color (or the closest color + * available). + */ + TEAM_COLOR_TRANSPARENT, + + /** + * Cages in stained hardened clay, using the team color (or the closest + * color available). + */ + TEAM_COLOR_SOLID, + + /** + * Cages in a custom provided block. + */ + CUSTOM + } + + /** + * A block + data value (storage class used to restore old blocks when the + * cage is destroyed). + */ + private class SimpleBlock + { + public Material material; + public MaterialData data; + + public SimpleBlock(Material material, MaterialData data) + { + this.material = material; + this.data = data; + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/game/TeleportationRunnable.java b/src/main/java/eu/carrade/amaury/UHCReloaded/game/TeleportationRunnable.java new file mode 100644 index 0000000..91059b3 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/game/TeleportationRunnable.java @@ -0,0 +1,97 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.game; + +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.tools.Callback; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Set; +import java.util.UUID; + + +/** + * @see Teleporter + */ +class TeleportationRunnable extends BukkitRunnable +{ + private final Teleporter teleporter; + private final Queue<UUID> teleportationQueue; + + private final Callback<UUID> onTeleportation; + private final Callback<UUID> onTeleportationSuccessful; + private final Callback<UUID> onTeleportationFailed; + private final Callback<Set<UUID>> onTeleportationProcessFinished; + + private final Set<UUID> failed = new HashSet<>(); + + public TeleportationRunnable(Teleporter teleporter, Set<UUID> playersToTeleport, Callback<UUID> onTeleportation, Callback<UUID> onTeleportationSuccessful, Callback<UUID> onTeleportationFailed, Callback<Set<UUID>> onTeleportationProcessFinished) + { + this.teleporter = teleporter; + this.onTeleportation = onTeleportation; + this.onTeleportationSuccessful = onTeleportationSuccessful; + this.onTeleportationFailed = onTeleportationFailed; + this.onTeleportationProcessFinished = onTeleportationProcessFinished; + + this.teleportationQueue = new ArrayDeque<>(playersToTeleport); + } + + @Override + public void run() + { + try + { + UUID player = teleportationQueue.remove(); + + UHUtils.callIfDefined(onTeleportation, player); + + if (teleporter.teleportPlayer(player, false)) + { + UHUtils.callIfDefined(onTeleportationSuccessful, player); + } + else + { + UHUtils.callIfDefined(onTeleportationFailed, player); + failed.add(player); + } + } + catch (NoSuchElementException e) // Queue empty + { + UHUtils.callIfDefined(onTeleportationProcessFinished, failed); + cancel(); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java new file mode 100644 index 0000000..7adb590 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/game/Teleporter.java @@ -0,0 +1,293 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.game; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.tools.Callback; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + + +/** + * Manages the initial teleportation process, and stores the spawn points of the players. + */ +public class Teleporter +{ + /** + * The spawn point designed for each player. + */ + private final Map<UUID, Location> spawnPoints = new HashMap<>(); + + /** + * The cages generated for each team + */ + private final Map<UUID, Cage> cages = new HashMap<>(); + + + /** + * Called when a player is teleported, during the teleportation process. + * + * <p>NOT called with {@link #teleportPlayer(UUID, Boolean)}.</p> + */ + private Callback<UUID> onTeleportation = null; + + /** + * Called when a player is teleported successfully, during the teleportation process. + * + * <p>NOT called with {@link #teleportPlayer(UUID, Boolean)}.</p> + */ + private Callback<UUID> onTeleportationSuccessful = null; + + /** + * Called when a player cannot be teleported (if offline, or without spawn...). + */ + private Callback<UUID> onTeleportationFailed = null; + + /** + * Called when the teleportation process started by {@link #startTeleportationProcess(Boolean)} + * ends. + */ + private Callback<Set<UUID>> onTeleportationProcessFinished = null; + + + /** + * Saves the spawn point of a player. + * + * @param playerUUID The player's UUID. + * @param spawn The spawn location. + */ + public void setSpawnForPlayer(final UUID playerUUID, final Location spawn) + { + spawnPoints.put(playerUUID, spawn); + } + + /** + * Checks if a spawn point is registered for the given player. + * + * @param playerUUID The player UUID. + * @return {@code true} if a spawn point is registered. + */ + public boolean hasSpawnForPlayer(final UUID playerUUID) + { + return spawnPoints.containsKey(playerUUID); + } + + /** + * @param playerUUID A player's UUID. + * @return The registered spawn point for that player, or {@code null} if no-one was ever registered. + */ + public Location getSpawnForPlayer(final UUID playerUUID) + { + return spawnPoints.get(playerUUID).clone(); + } + + + /** + * Registers a cage for a player. + * + * @param player The player + * @param cage The cage + */ + public void setCageForPlayer(final UUID player, final Cage cage) + { + cages.put(player, cage); + } + + /** + * Checks if a cage is registered for the given player. + * @param player The player. + * @return {@code true} if a cage is registered. + */ + public boolean hasCageForPlayer(final UUID player) + { + return cages.containsKey(player); + } + + /** + * @param player A player + * @return The registered {@link Cage} for this player, or {@code null} if no one is registered. + */ + public Cage getCageForPlayer(final UUID player) + { + return cages.get(player); + } + + + /** + * Teleports the given player to the spawn point. + * + * @param playerUUID The player's UUID. + * @param teleportOnGround if {@code true} the player will be teleported on the ground; else, at + * the location directly. + * + * @return {@code true} if the player was teleported (i.e. was online and with an associated + * spawn point). + */ + public boolean teleportPlayer(UUID playerUUID, Boolean teleportOnGround) + { + Player player = Bukkit.getPlayer(playerUUID); + if (player == null) + return false; + + Location spawn = spawnPoints.get(playerUUID); + + if (spawn == null) + return false; + + else if (teleportOnGround) + spawn = spawn.getWorld().getHighestBlockAt(spawn).getLocation().add(0, 2, 0); + + if (!teleportOnGround) + { + final Cage cage = cages.get(playerUUID); + if (cage != null) cage.build(); + } + + player.teleport(spawn); + return true; + } + + + /** + * Registers a callback called while trying to teleport a player. + * + * @param callback The callback. Argument: the teleported player's UUID. + * + * @return Same instance for chaining. + */ + public Teleporter whenTeleportationOccurs(Callback<UUID> callback) + { + onTeleportation = callback; + return this; + } + + /** + * Registers a callback called when a player is teleported successfully. + * + * @param callback The callback. Argument: the non-teleported player's UUID. + * + * @return Same instance for chaining. + */ + public Teleporter whenTeleportationSuccesses(Callback<UUID> callback) + { + onTeleportationSuccessful = callback; + return this; + } + + /** + * Registers a callback called when a player cannot be teleported. + * + * @param callback The callback. Argument: the non-teleported player's UUID. + * + * @return Same instance for chaining. + */ + public Teleporter whenTeleportationFails(Callback<UUID> callback) + { + onTeleportationFailed = callback; + return this; + } + + /** + * Registers a callback called when the whole teleportation process (started with {@link + * #startTeleportationProcess(Boolean)}) ends. + * + * <p>This callback is NOT called when {@link #teleportPlayer(UUID, Boolean)} is used.</p> + * + * @param callback The callback. Argument: a set containing the UUID of all non-teleported + * players. + * + * @return Same instance for chaining. + */ + public Teleporter whenTeleportationEnds(Callback<Set<UUID>> callback) + { + onTeleportationProcessFinished = callback; + return this; + } + + + /** + * Teleports the players. + * + * @param slowMode if {@code true}, the players will be slowly teleported one by one, with a + * delay between them. + */ + public void startTeleportationProcess(Boolean slowMode) + { + // Fast mode: we loop on the spawn points and teleport everyone. Bim. + if (!slowMode) + { + Set<UUID> fails = new HashSet<>(); + + for (UUID playerUUID : spawnPoints.keySet()) + { + UHUtils.callIfDefined(onTeleportation, playerUUID); + + if (teleportPlayer(playerUUID, false)) + { + UHUtils.callIfDefined(onTeleportationSuccessful, playerUUID); + } + else + { + UHUtils.callIfDefined(onTeleportationFailed, playerUUID); + fails.add(playerUUID); + } + } + + UHUtils.callIfDefined(onTeleportationProcessFinished, fails); + } + + // Slow mode + else + { + new TeleportationRunnable(this, spawnPoints.keySet(), onTeleportation, onTeleportationSuccessful, onTeleportationFailed, onTeleportationProcessFinished) + .runTaskTimer(UHCReloaded.get(), 1l, UHConfig.START.SLOW.DELAY_BETWEEN_TP.get() * 20l); + } + } + + /** + * Cleanups the cages left by the teleportation process, to be executed when the game really starts. + */ + public void cleanup() + { + for (final Cage nicolas : cages.values()) // sorry + nicolas.destroy(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java new file mode 100644 index 0000000..020da0f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java @@ -0,0 +1,1424 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.game; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.events.EpisodeChangedCause; +import eu.carrade.amaury.UHCReloaded.events.UHEpisodeChangedEvent; +import eu.carrade.amaury.UHCReloaded.events.UHGameStartsEvent; +import eu.carrade.amaury.UHCReloaded.events.UHPlayerResurrectedEvent; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import eu.carrade.amaury.UHCReloaded.protips.ProTips; +import eu.carrade.amaury.UHCReloaded.task.FireworksOnWinnersTask; +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.teams.TeamManager; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.ColorsUtils; +import eu.carrade.amaury.UHCReloaded.utils.UHSound; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.rawtext.RawText; +import fr.zcraft.zlib.tools.Callback; +import fr.zcraft.zlib.tools.runners.RunTask; +import fr.zcraft.zlib.tools.text.ActionBar; +import fr.zcraft.zlib.tools.text.RawMessage; +import fr.zcraft.zlib.tools.text.Titles; +import org.bukkit.Achievement; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Difficulty; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + + +public class UHGameManager +{ + public final boolean START_GIVE_BANNER; + public final boolean START_PLACE_BANNER_HEAD; + public final boolean START_PLACE_BANNER_SPAWN; + + private final Boolean RANDOM_COLORS_IN_SOLO; + private final Boolean BROADCAST_SLOW_START_PROGRESS; + private final Long GRACE_PERIOD; + private final Long PEACE_PERIOD; + private final Long SURFACE_MOBS_FREE_PERIOD; + private final UHSound DEATH_SOUND; + + private UHCReloaded p = null; + private TeamManager tm = null; + private Random random = null; + + private Boolean damagesEnabled = false; + private Boolean mobsOnSurface = false; + + private HashSet<String> players = new HashSet<>(); // Will be converted to UUID when a built-in API for name->UUID conversion will be available + private HashSet<UUID> alivePlayers = new HashSet<>(); + private HashSet<UHTeam> aliveTeams = new HashSet<>(); + private HashSet<UUID> spectators = new HashSet<>(); + private Map<UUID, Location> deathLocations = new HashMap<>(); + + private HashSet<String> deadPlayersToBeResurrected = new HashSet<>(); // Same + + private Integer alivePlayersCount = 0; + private Integer aliveTeamsCount = 0; + + private Boolean gameWithTeams = true; + + // Used for the slow start. + private Boolean slowStartInProgress = false; + private Boolean slowStartTPFinished = false; + + private Boolean gameStarted = false; + private Boolean gameFinished = false; + private Integer episode = 0; + + private Teleporter teleporter = null; + + // Used to send a contextual error message in UHCommandManager, using only one exception, + // by checking the message. (Used in this.finishGame().) + public final static String FINISH_ERROR_NOT_STARTED = "Unable to finish the game: the game is not started"; + public final static String FINISH_ERROR_NOT_FINISHED = "Unable to finish the game: the game is not finished"; + + + public UHGameManager(UHCReloaded plugin) + { + this.p = plugin; + this.tm = p.getTeamManager(); + + this.random = new Random(); + + + // Loads the config + + RANDOM_COLORS_IN_SOLO = UHConfig.TEAMS_OPTIONS.RANDOM_COLORS.get(); + + BROADCAST_SLOW_START_PROGRESS = UHConfig.START.SLOW.BROADCAST_PROGRESS.get(); + + GRACE_PERIOD = (long) Math.max(UHUtils.string2Time(UHConfig.START.GRACE_PERIOD.get(), 30), 15) * 20l; + PEACE_PERIOD = (long) UHUtils.string2Time(UHConfig.START.PEACE_PERIOD.get(), 0) * 20l; + SURFACE_MOBS_FREE_PERIOD = (long) UHUtils.string2Time(UHConfig.START.SURFACE_MOBS_FREE_PERIOD.get(), 900) * 20l; + + DEATH_SOUND = new UHSound(UHConfig.DEATH.ANNOUNCEMENTS.SOUND); + + START_GIVE_BANNER = UHConfig.TEAMS_OPTIONS.BANNER.GIVE.GIVE_IN_HOTBAR.get(); + START_PLACE_BANNER_SPAWN = UHConfig.TEAMS_OPTIONS.BANNER.GIVE.PLACE_ON_SPAWN.get(); + START_PLACE_BANNER_HEAD = UHConfig.TEAMS_OPTIONS.BANNER.GIVE.GIVE_IN_HEAD.get(); + } + + /** + * Initializes the environment before the start of the game. + */ + public void initEnvironment() + { + p.getServer().getWorlds().get(0).setGameRuleValue("doDaylightCycle", "false"); + p.getServer().getWorlds().get(0).setTime(6000L); + p.getServer().getWorlds().get(0).setStorm(false); + p.getServer().getWorlds().get(0).setDifficulty(Difficulty.HARD); + } + + /** + * Initializes the given player. + * + * - Teleportation to the default world's spawn point. + * - Max food level & health. + * - Scoreboard. + * - Fixed health score. + * - Spectate mode disabled. + * - Gamemode: creative (if permission "uh.build" granted) or adventure (else). + * + * @param player + */ + public void initPlayer(final Player player) + { + if (UHConfig.TELEPORT_TO_SPAWN_IF_NOT_STARTED.get()) + { + Location l = player.getWorld().getSpawnLocation().add(0.5, 0.5, 0.5); + if (!UHUtils.safeTP(player, l)) + { + player.teleport(l.add(0, 1, 0)); + } + } + + player.setFoodLevel(20); + player.setSaturation(20f); + player.setHealth(20d); + + p.getScoreboardManager().setScoreboardForPlayer(player); + + // Used to update the "health" objective, to avoid a null one. + // Launched later because else, the health is constantly set to 20, + // and this prevents the health score to be updated. + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + p.getScoreboardManager().updateHealthScore(player); + } + }, 20L); + + // Disable the spectator mode if the game is not started. + p.getSpectatorsManager().setSpectating(player, false); + + // Resets the achievements + if (UHConfig.ACHIEVEMENTS.RESET_ACHIEVEMENTS_AT_STARTUP.get()) + { + player.removeAchievement(Achievement.OPEN_INVENTORY); + } + + // If the user has the permission to build before the game, he will probably needs + // the creative mode. + if (!player.hasPermission("uh.build")) + { + player.setGameMode(GameMode.ADVENTURE); + } + else + { + player.setGameMode(GameMode.CREATIVE); + } + } + + + /** + * Starts the game. + * + * - Teleports the teams + * - Changes the gamemode, reset the life, clear inventories, etc. + * - Launches the timer + * + * @param sender The player who launched the game. + * @param slow If true, the slow mode is enabled. With the slow mode, the players are, at + * first, teleported one by one with a configurable delay, and with the + * fly. Then, the fly is removed and the game starts. + * @param ignoreTeams If true, the players will be teleported in individual teleportation spots, + * just like without teams, even with teams. + * + * @throws IllegalStateException if the game is running. + */ + public void start(final CommandSender sender, final Boolean slow, Boolean ignoreTeams) throws IllegalStateException + { + if (isGameRunning()) + { + throw new IllegalStateException("The game is currently running!"); + } + + + /** Initialization of the teams **/ + + alivePlayers.clear(); + aliveTeams.clear(); + alivePlayersCount = 0; + aliveTeamsCount = 0; + + // Stores the teams created on-the-fly, to unregister them if something bad happens. + Set<UHTeam> onTheFlyTeams = new HashSet<>(); + + // If there isn't any team, we add all players (startup spectators excluded) to a new solo team. + if (tm.getTeams().isEmpty()) + { + gameWithTeams = false; + + for (Player player : Bukkit.getOnlinePlayers()) + { + if (!spectators.contains(player.getUniqueId())) + { + UHTeam team = new UHTeam(player.getName(), RANDOM_COLORS_IN_SOLO ? TeamColor.RANDOM : null); + + team.addPlayer(player, true); + + tm.addTeam(team); + onTheFlyTeams.add(team); + } + } + } + + // Else, every non-startup-spectator out of any team player is added to a solo team. + else + { + gameWithTeams = true; + + for (Player player : Bukkit.getOnlinePlayers()) + { + if (!spectators.contains(player.getUniqueId()) && tm.getTeamForPlayer(player) == null) + { + // We need an unique name for the team. + String teamName = player.getName(); + while (tm.isTeamRegistered(teamName)) + { + teamName = player.getName() + " " + random.nextInt(1000000); + } + + UHTeam team = new UHTeam(teamName, RANDOM_COLORS_IN_SOLO ? TeamColor.RANDOM : null); + + team.addPlayer(player, true); + + tm.addTeam(team); + onTheFlyTeams.add(team); + } + } + } + + + /** Initialization of the players **/ + + for (UHTeam team : tm.getTeams()) + { + for (OfflinePlayer player : team.getPlayers()) + { + if (!spectators.contains(player.getUniqueId())) + { + alivePlayers.add(player.getUniqueId()); + } + } + } + + updateAliveCache(); + + + /** Spawns check **/ + + Integer spawnsNeeded = ignoreTeams ? alivePlayersCount : aliveTeamsCount; + + if (p.getSpawnsManager().getSpawnPoints().size() < spawnsNeeded) + { + if (sender instanceof Player) sender.sendMessage(""); + sender.sendMessage(I.t("{ce}Unable to start the game: not enough teleportation spots.")); + sender.sendMessage(I.t("{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to generate the missing spawns automatically.")); + + /// In the sentence: "Or click here to generate the spawns randomly." + RawMessage.send(sender, new RawText(I.t("Or")) + .then(" ") + /// In the sentence: "Or click here to generate the spawns randomly." + .then(I.t("click here")) + .color(ChatColor.GREEN).style(ChatColor.BOLD) + .command("/uh spawns generate random") + .hover(new RawText("/uh spawns generate random")) + .then(" ") + /// In the sentence: "Or click here to generate the spawns randomly." + .then(I.t("to generate the spawns randomly.")).color(ChatColor.WHITE) + .build() + ); + + // We clears the teams created on-the-fly + for (UHTeam team : onTheFlyTeams) + { + tm.removeTeam(team, true); + } + + aliveTeamsCount = 0; + alivePlayersCount = 0; + + return; + } + + + /** MOTD (now the game WILL start) **/ + + p.getMOTDManager().updateMOTDDuringStart(); + + + /** Removes the teams action bar (if any) **/ + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + { + for (UHTeam team : tm.getTeams()) + { + for (OfflinePlayer player : team.getPlayers()) + { + ActionBar.removeMessage(player.getUniqueId(), true); + } + } + } + + /** Initialization of the spectator mode **/ + + for (Player player : Bukkit.getOnlinePlayers()) + { + p.getSpectatorsManager().setSpectating(player, spectators.contains(player.getUniqueId())); + } + + + /** Teleportation **/ + + teleporter = new Teleporter(); + + List<Location> spawnPoints = new ArrayList<>(p.getSpawnsManager().getSpawnPoints()); + Collections.shuffle(spawnPoints); + + Queue<Location> unusedTP = new ArrayDeque<>(spawnPoints); + + for (final UHTeam team : tm.getTeams()) + { + if (team.isEmpty()) continue; + + Material cageMaterial = null; + Byte cageData = null; + + if (UHConfig.START.SLOW.CAGES.ENABLED.get()) + { + switch (UHConfig.START.SLOW.CAGES.TYPE.get()) + { + case TEAM_COLOR_TRANSPARENT: + cageMaterial = Material.STAINED_GLASS; + cageData = ColorsUtils.chat2Dye(team.getColor().toChatColor()).getWoolData(); + break; + + case TEAM_COLOR_SOLID: + cageMaterial = Material.STAINED_CLAY; + cageData = ColorsUtils.chat2Dye(team.getColor().toChatColor()).getWoolData(); + break; + + case CUSTOM: + cageMaterial = UHConfig.START.SLOW.CAGES.CUSTOM_BLOCK.get(); + break; + } + } + + if (!ignoreTeams && gameWithTeams) + { + final Location teamSpawn = unusedTP.poll(); + + Cage cage = null; + if (cageMaterial != null) + { + cage = new Cage(teamSpawn, UHConfig.START.SLOW.CAGES.BUILD_CEILING.get(), UHConfig.START.SLOW.CAGES.VISIBLE_WALLS.get()); + cage.setCustomMaterial(cageMaterial, cageData != null ? cageData : 0); + cage.setInternalHeight(UHConfig.START.SLOW.CAGES.HEIGHT.get()); + cage.setRadius(UHConfig.START.SLOW.CAGES.RADIUS.get()); + } + + p.getDynmapIntegration().showSpawnLocation(team, teamSpawn); + + for (final UUID player : team.getPlayersUUID()) + { + teleporter.setSpawnForPlayer(player, teamSpawn); + if (cage != null) teleporter.setCageForPlayer(player, cage); + } + } + else + { + for (final UUID player : team.getPlayersUUID()) + { + final Location playerSpawn = unusedTP.poll(); + + Cage cage = null; + if (cageMaterial != null) + { + cage = new Cage(playerSpawn, UHConfig.START.SLOW.CAGES.BUILD_CEILING.get(), UHConfig.START.SLOW.CAGES.VISIBLE_WALLS.get()); + cage.setCustomMaterial(cageMaterial, cageData != null ? cageData : 0); + cage.setInternalHeight(UHConfig.START.SLOW.CAGES.HEIGHT.get()); + cage.setRadius(UHConfig.START.SLOW.CAGES.RADIUS.get()); + } + + teleporter.setSpawnForPlayer(player, playerSpawn); + if (cage != null) teleporter.setCageForPlayer(player, cage); + + p.getDynmapIntegration().showSpawnLocation(Bukkit.getOfflinePlayer(player), playerSpawn); + } + } + } + + if (slow) + { + slowStartInProgress = true; + slowStartTPFinished = false; + + // The players are frozen during the start (if cages are not used). + if (!UHConfig.START.SLOW.CAGES.ENABLED.get()) + p.getFreezer().setGlobalFreezeState(true, false); + + // A simple information, because this start is slower (yeah, Captain Obvious here) + p.getServer().broadcastMessage(I.t("{lightpurple}Teleportation in progress... Please wait.")); + + teleporter.whenTeleportationOccurs(new Callback<UUID>() + { + private int teleported = 0; + private final int total = alivePlayersCount; + + @Override + public void call(UUID uuid) + { + teleported++; + + if (BROADCAST_SLOW_START_PROGRESS) + { + /// Displayed in the action bar while the slow teleportation occurs. + final String message = I.t("{lightpurple}Teleporting... {gray}({0}/{1})", teleported, total); + for (Player player : Bukkit.getOnlinePlayers()) + { + ActionBar.sendPermanentMessage(player, message); + } + } + } + }); + } + + teleporter + .whenTeleportationSuccesses(new Callback<UUID>() + { + @Override + public void call(UUID uuid) + { + final Player player = Bukkit.getPlayer(uuid); + + if (slow) + { + sender.sendMessage(I.t("{gray}Player {0}{gray} teleported.", player.getName())); + + if (!UHConfig.START.SLOW.CAGES.ENABLED.get()) + { + RunTask.nextTick(new Runnable() + { + @Override + public void run() + { + player.setAllowFlight(true); + player.setFlying(true); + } + }); + } + } + + if (UHConfig.START.SLOW.CAGES.ENABLED.get()) + player.setGameMode(GameMode.ADVENTURE); + else + player.setGameMode(GameMode.SURVIVAL); + + player.setHealth(20D); + player.setFoodLevel(20); + player.setSaturation(20); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.setExp(0L); + player.setLevel(0); + player.closeInventory(); + + for (PotionEffect effect : player.getActivePotionEffects()) + { + player.removePotionEffect(effect.getType()); + } + + player.setCompassTarget(player.getWorld().getSpawnLocation()); + } + }) + + .whenTeleportationFails(new Callback<UUID>() + { + @Override + public void call(UUID uuid) + { + + } + }) + + .whenTeleportationEnds(new Callback<Set<UUID>>() + { + @Override + public void call(Set<UUID> uuids) + { + if (slow) + { + slowStartTPFinished = true; + + try + { + sender.sendMessage(I.t("{cs}All teams are teleported.")); + RawMessage.send(sender, new RawText(I.t("{gray}Use {cc}/uh start{gray} or click here to start the game.")) + .hover(new RawText(I.t("Click here to start the game"))) + .command("/uh start") + ); + } + catch (NullPointerException ignored) {} + + if (BROADCAST_SLOW_START_PROGRESS) + { + /// Displayed in the action bar when the slow teleportation is finished but the game not started. + String message = I.t("{lightpurple}Teleportation complete. {gray}The game will start soon..."); + for (Player player : Bukkit.getOnlinePlayers()) + { + ActionBar.sendPermanentMessage(player, message); + } + } + } + else + { + startEnvironment(); + startTimer(); + scheduleDamages(); + sendStartupProTips(); + finalizeStart(); + } + } + }) + + .startTeleportationProcess(slow); + } + + /** + * Finalizes the start of the game, with the slow mode. Removes the fly and ends the start + * (environment, timer...) + * + * @param sender The sender of the {@code /uh start slow go} command + */ + public void finalizeStartSlow(CommandSender sender) + { + if (!slowStartInProgress) + { + sender.sendMessage(I.t("{ce}Please execute {cc}/uh start slow:true{ce} before.")); + return; + } + + if (!slowStartTPFinished) + { + sender.sendMessage(I.t("{ce}Please wait while the players are teleported.")); + return; + } + + // The freeze is removed. + if (!UHConfig.START.SLOW.CAGES.ENABLED.get()) + { + p.getFreezer().setGlobalFreezeState(false, false); + + // The fly is removed to everyone + for (Player player : p.getServer().getOnlinePlayers()) + { + if (alivePlayers.contains(player.getUniqueId())) + { + player.setFlying(false); + player.setAllowFlight(false); + } + } + } + + // The action bar is cleared + if (BROADCAST_SLOW_START_PROGRESS) + { + for (Player player : Bukkit.getOnlinePlayers()) + { + ActionBar.removeMessage(player); + } + } + + // The environment is initialized, the game is started. + startEnvironment(); + startTimer(); + scheduleDamages(); + sendStartupProTips(); + finalizeStart(); + + slowStartInProgress = false; + } + + /** + * Initializes the environment at the beginning of the game. + */ + private void startEnvironment() + { + World overworld = UHUtils.getOverworld(); + + if (overworld != null) + { + overworld.setGameRuleValue("doDaylightCycle", (UHConfig.DAYLIGHT_CYCLE.DO.get()).toString()); + overworld.setTime(UHConfig.DAYLIGHT_CYCLE.TIME.get()); + overworld.setStorm(false); + } + + for (World world : Bukkit.getWorlds()) + { + world.setGameRuleValue("keepInventory", Boolean.FALSE.toString()); // Just in case... + world.setGameRuleValue("naturalRegeneration", (UHConfig.GAMEPLAY_CHANGES.NATURAL_REGENERATION.get()).toString()); + world.setDifficulty(Difficulty.HARD); + } + } + + /** + * Launches the timer by launching the task that updates the scoreboard every second. + */ + private void startTimer() + { + if (UHConfig.EPISODES.ENABLED.get()) + { + this.episode = 1; + + // An empty string is used for the name of the main timer, because + // such a name can't be used by players. + UHTimer mainTimer = new UHTimer(""); + mainTimer.setDuration(this.getEpisodeLength()); + + p.getTimerManager().registerMainTimer(mainTimer); + + mainTimer.start(); + } + } + + /** + * Enables the damages 30 seconds (600 ticks) later, the PvP after if needed, and the mobs spawns. + */ + private void scheduleDamages() + { + // When the grace period is over, damages are enabled. + RunTask.later(new Runnable() + { + @Override + public void run() + { + damagesEnabled = true; + + if (UHConfig.START.BROADCAST_GRACE_END.get()) + { + Bukkit.broadcastMessage(I.t("{red}{bold}Warning!{white} The grace period ended, you are now vulnerable.")); + } + } + }, GRACE_PERIOD); + + // When the peace period is over, PVP is enabled + if (PEACE_PERIOD > 0) + { + for (World world : Bukkit.getWorlds()) + world.setPVP(false); + + RunTask.later(new Runnable() + { + @Override + public void run() + { + for (World world : Bukkit.getWorlds()) + world.setPVP(true); + + Bukkit.broadcastMessage(I.t("{red}{bold}Warning!{white} PvP is now enabled.")); + } + }, PEACE_PERIOD); + } + + // Allows mobs to spawn on the surface after the mobs-free period + RunTask.later(new Runnable() + { + @Override + public void run() + { + mobsOnSurface = true; + } + }, SURFACE_MOBS_FREE_PERIOD); + } + + /** + * Sends two ProTips: + * - about the team chat, to all players, 20 seconds after the beginning of the game; + * - about the invincibility, 5 seconds after the beginning of the game. + */ + private void sendStartupProTips() + { + // Team chat - 20 seconds after + if (this.isGameWithTeams()) + { + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + for (Player player : getOnlineAlivePlayers()) + { + ProTips.USE_T_COMMAND.sendTo(player); + } + } + }, 400L); + } + + // Invincibility - 5 seconds after + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + for (Player player : getOnlineAlivePlayers()) + { + ProTips.STARTUP_INVINCIBILITY.sendTo(player); + } + } + }, 100L); + } + + /** + * Changes the state of the game. Also, forces the global freeze start to false, to avoid toggle + * bugs (like inverted state). + */ + private void finalizeStart() + { + p.getFreezer().setGlobalFreezeState(false); + + teleporter.cleanup(); + + gameStarted = true; + gameFinished = false; + + updateAliveCache(); + + // Survival gamemode for everyone + for (Player player : p.getServer().getOnlinePlayers()) + { + if (alivePlayers.contains(player.getUniqueId())) + { + player.setGameMode(GameMode.SURVIVAL); + } + } + + // Fires the event + p.getServer().getPluginManager().callEvent(new UHGameStartsEvent()); + } + + /** + * @return true if the slow start is in progress. + */ + public boolean isSlowStartInProgress() + { + return slowStartInProgress; + } + + /** + * Updates the cached values of the alive players and teams. + */ + public void updateAliveCache() + { + // Alive teams + aliveTeams.clear(); + for (UHTeam t : tm.getTeams()) + { + for (UUID pid : t.getPlayersUUID()) + { + if (!this.isPlayerDead(pid)) aliveTeams.add(t); + } + } + + // Counters + this.alivePlayersCount = alivePlayers.size(); + this.aliveTeamsCount = aliveTeams.size(); + + if (isGameRunning()) + p.getMOTDManager().updateMOTDDuringGame(); + } + + /** + * Updates the cached values of the alive players and teams. + * + * @deprecated Use {@link #updateAliveCache()} instead. + */ + @Deprecated + public void updateAliveCounters() { updateAliveCache(); } + + + /** + * Shifts an episode. + * + * @param shifter The player who shifts the episode, an empty string if the episode is shifted + * because the timer is up. + */ + public void shiftEpisode(String shifter) + { + if (UHConfig.EPISODES.ENABLED.get()) + { + this.episode++; + + EpisodeChangedCause cause; + if (shifter.equals("")) cause = EpisodeChangedCause.FINISHED; + else cause = EpisodeChangedCause.SHIFTED; + + // Restarts the timer. + // Useless for a normal start (restarted in the event), but needed if the episode was shifted. + if (cause == EpisodeChangedCause.SHIFTED) + { + p.getTimerManager().getMainTimer().start(); + } + + p.getServer().getPluginManager().callEvent(new UHEpisodeChangedEvent(episode, cause, shifter)); + } + } + + /** + * Shift an episode because the timer is up. + */ + public void shiftEpisode() + { + shiftEpisode(""); + } + + + /** + * Resurrects an offline player. The tasks that needed to be executed when the player is online + * are delayed and executed when the player joins. + * + * @param playerName The name of the player to resurrect + * + * @return true if the player was dead, false otherwise. + */ + public boolean resurrect(String playerName) + { + Player playerOnline = Bukkit.getPlayer(playerName); + + if (playerOnline != null && playerOnline.isOnline()) + { + return resurrectPlayerOnlineTask(playerOnline); + } + else + { + // We checks if the player was a player + if (!this.players.contains(playerName)) + { + return false; + } + } + + // So, now, we are sure that the player is really offline. + // The task needed to be executed will be executed when the player join. + this.deadPlayersToBeResurrected.add(playerName); + + return true; + } + + /** + * The things that have to be done in order to resurrect the players and that needs the player + * to be online. + * + * @param player The player to resurrect + * + * @return true if the player was dead, false otherwise. + */ + public boolean resurrectPlayerOnlineTask(Player player) + { + if (alivePlayers.contains(player.getUniqueId())) + { + return false; + } + + // Player registered as alive + alivePlayers.add(player.getUniqueId()); + updateAliveCache(); + + // This method can be used to add a player after the game start. + if (!players.contains(player.getName())) + { + players.add(player.getName()); + } + + // Event + p.getServer().getPluginManager().callEvent(new UHPlayerResurrectedEvent(player)); + + return true; + } + + /** + * Returns true if a player need to be resurrected. + * + * @param player + * + * @return + */ + public boolean isDeadPlayersToBeResurrected(Player player) + { + return deadPlayersToBeResurrected.contains(player.getName()); + } + + /** + * Registers a player as resurrected. + * + * @param player + */ + public void markPlayerAsResurrected(Player player) + { + deadPlayersToBeResurrected.remove(player.getName()); + } + + + /** + * This method saves the location of the death of a player. + * + * @param player + * @param location + */ + public void addDeathLocation(Player player, Location location) + { + deathLocations.put(player.getUniqueId(), location); + } + + /** + * This method removes the stored death location. + * + * @param player + */ + public void removeDeathLocation(Player player) + { + deathLocations.remove(player.getUniqueId()); + } + + /** + * This method returns the stored death location. + * + * @param player The player to retrieve the death location of. + * + * @return The death location, or {@code null} if not defined. + */ + public Location getDeathLocation(Player player) + { + if (deathLocations.containsKey(player.getUniqueId())) + { + return deathLocations.get(player.getUniqueId()); + } + + return null; + } + + /** + * This method returns true if a death location is stored for the given player. + * + * @param player The player to check the death location of. + * + * @return {@code true} if a death location is set. + */ + public boolean hasDeathLocation(Player player) + { + return deathLocations.containsKey(player.getUniqueId()); + } + + /** + * Adds a spectator. When the game is started, spectators are ignored and the spectator mode is + * enabled if SpectatorPlus is present. + * + * @param player The player to register as a spectator. + */ + public void addStartupSpectator(OfflinePlayer player) + { + spectators.add(player.getUniqueId()); + tm.removePlayerFromTeam(player); + } + + /** + * Removes a spectator. + * + * @param player The spectator to remove. + */ + public void removeStartupSpectator(OfflinePlayer player) + { + spectators.remove(player.getUniqueId()); + } + + /** + * Returns a list of the current registered spectators. + * + * This returns only a list of the <em>initial</em> spectators. Use {@link #getAlivePlayers()} + * to get the alive players, and remove the elements of this list from the online players to get + * the spectators. + * + * @return The initial spectators. + */ + public HashSet<String> getStartupSpectators() + { + HashSet<String> spectatorNames = new HashSet<>(); + + for (UUID id : spectators) + { + final OfflinePlayer player = OfflinePlayersLoader.getOfflinePlayer(id); + final String playerName = player.getName(); + + if (playerName != null) + spectatorNames.add(playerName); + else + /// Spectators list item if the nick cannot be found + spectatorNames.add(I.t("Unknown player with UUID {0}", player.getUniqueId())); + } + + return spectatorNames; + } + + /** + * @return true if the game was launched and is not finished. + */ + public boolean isGameRunning() + { + return gameStarted && !gameFinished; + } + + /** + * @return true if the game is started. + */ + public boolean isGameStarted() + { + return gameStarted; + } + + /** + * @return true if the game is finished. + */ + public boolean isGameFinished() + { + return gameFinished; + } + + /** + * Registers the state of the game. + * + * @param finished If true, the game will be marked as finished. + */ + public void setGameFinished(boolean finished) + { + gameFinished = finished; + } + + /** + * @return true if the game is a game with teams, and false if the game is a solo game. + */ + public boolean isGameWithTeams() + { + return gameWithTeams; + } + + /** + * @return true if damages are enabled. Damages are enabled 30 seconds after the beginning of + * the game. + */ + public boolean isTakingDamage() + { + return damagesEnabled; + } + + public boolean isSurfaceSpawnEnabled() + { + return mobsOnSurface; + } + + /** + * Returns true if the given player is dead. + * + * @param player The player. + * + * @return True if the player is dead. + */ + public boolean isPlayerDead(Player player) + { + return !alivePlayers.contains(player.getUniqueId()); + } + + /** + * Returns true if the given player is dead. + * + * @param player The UUID of the player. + * + * @return True if the player is dead. + */ + public boolean isPlayerDead(UUID player) + { + return !alivePlayers.contains(player); + } + + /** + * Registers a player as dead. + * + * @param player The player to mark as dead. + */ + public void addDead(Player player) + { + alivePlayers.remove(player.getUniqueId()); + updateAliveCache(); + } + + /** + * Registers a player as dead. + * + * @param player The UUID of the player to mark as dead. + */ + public void addDead(UUID player) + { + alivePlayers.remove(player); + updateAliveCache(); + } + + + /** + * Broadcasts the winner(s) of the game and launches some fireworks + * + * @throws IllegalStateException if the game is not started or not finished (use the message to + * distinguish these cases, {@link #FINISH_ERROR_NOT_STARTED} or + * {@link #FINISH_ERROR_NOT_FINISHED}). + */ + public void finishGame() + { + if (!p.getGameManager().isGameStarted()) + { + throw new IllegalStateException(FINISH_ERROR_NOT_STARTED); + } + + if (p.getGameManager().getAliveTeamsCount() != 1) + { + throw new IllegalStateException(FINISH_ERROR_NOT_FINISHED); + } + + // There's only one team. + UHTeam winnerTeam = p.getGameManager().getAliveTeams().iterator().next(); + Set<OfflinePlayer> listWinners = winnerTeam.getPlayers(); + + if (UHConfig.FINISH.MESSAGE.get()) + { + if (isGameWithTeams()) + { + String winners = ""; + int j = 0; + + for (OfflinePlayer winner : listWinners) + { + if (j != 0) + { + if (j == listWinners.size() - 1) + { + /// The "and" in the winners players list (like "player1, player2 and player3"). + winners += " " + I.tc("winners_list", "and") + " "; + } + else + { + winners += ", "; + } + } + + winners += winner.getName(); + j++; + } + + p.getServer().broadcastMessage(I.t("{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) for their victory! {darkgreen}{obfuscated}--", winners, winnerTeam.getDisplayName())); + } + else + { + p.getServer().broadcastMessage(I.t("{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! {darkgreen}{obfuscated}--", winnerTeam.getName())); + } + } + + if (UHConfig.FINISH.TITLE.get()) + { + final String title; + final String subtitle; + + if (isGameWithTeams()) + { + /// The main title of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). + title = I.t("{darkgreen}{0}", winnerTeam.getDisplayName()); + /// The subtitle of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). + subtitle = I.t("{green}This team wins the game!", winnerTeam.getDisplayName()); + } + else + { + /// The main title of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). + title = I.t("{darkgreen}{0}", winnerTeam.getDisplayName()); + /// The subtitle of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). + subtitle = I.t("{green}wins the game!", winnerTeam.getDisplayName()); + } + + Titles.broadcastTitle(5, 142, 21, title, subtitle); + } + + if (UHConfig.FINISH.FIREWORKS.ENABLED.get()) + { + new FireworksOnWinnersTask(listWinners).runTaskTimer(p, 0l, 10l); + } + } + + /** + * Returns the names of the players of this game. + * + * @return The set. + */ + public HashSet<String> getPlayers() + { + return players; + } + + /** + * Returns a list of the currently alive teams. + * + * @return The set. + */ + public Set<UHTeam> getAliveTeams() + { + return aliveTeams; + } + + /** + * Returns a list of the currently alive players. + * + * @return The set. + */ + public Set<OfflinePlayer> getAlivePlayers() + { + + HashSet<OfflinePlayer> alivePlayersList = new HashSet<>(); + + for (UUID id : alivePlayers) + { + alivePlayersList.add(p.getServer().getOfflinePlayer(id)); + } + + return alivePlayersList; + } + + /** + * Returns a list of the currently alive and online players. + * + * @return The list. + */ + public HashSet<Player> getOnlineAlivePlayers() + { + + HashSet<Player> alivePlayersList = new HashSet<>(); + + for (UUID id : alivePlayers) + { + Player player = p.getServer().getPlayer(id); + if (player != null) + { + alivePlayersList.add(player); + } + } + + return alivePlayersList; + } + + /** + * @return the death sound, or null if no death sound is registered. + */ + public UHSound getDeathSound() + { + return DEATH_SOUND; + } + + /** + * @return the length of one episode, in seconds. + */ + public Integer getEpisodeLength() + { + return UHUtils.string2Time(UHConfig.EPISODES.LENGTH.get(), 20*60); + } + + /** + * @return the (cached) number of alive players. + */ + public Integer getAlivePlayersCount() + { + return alivePlayersCount; + } + + /** + * @return the (cached) number of alive teams. + */ + public Integer getAliveTeamsCount() + { + return aliveTeamsCount; + } + + /** + * @return the number of the current episode. + */ + public Integer getEpisode() + { + return episode; + } + + + /** + * @return the teleporter instance used to start the game, containing the spawn points of each + * player. + */ + public Teleporter getTeleporter() + { + return teleporter; + } + + + + /* *** Deprecated methods *** */ + + /** + * Adds a spectator. When the game is started, spectators are ignored and the spectator mode is + * enabled if SpectatorPlus is present. + * + * @param player The player to register as a spectator. + * + * @deprecated Use {@link #addStartupSpectator(Player)} instead. + */ + @Deprecated + public void addSpectator(Player player) + { + addStartupSpectator(player); + } + + /** + * Removes a spectator. + * + * @param player + * + * @deprecated Use {@link #removeStartupSpectator(Player)} instead. + */ + @Deprecated + public void removeSpectator(Player player) + { + removeStartupSpectator(player); + } + + /** + * Returns a list of the current registered spectators. + * + * This returns only a list of the <em>initial</em> spectators. Use {@link #getAlivePlayers()} + * to get the alive players, and remove the elements of this list from the online players to get + * the spectators. + * + * @return The initial spectators. + * @deprecated Use {@link #getStartupSpectators()} instead. + */ + @Deprecated + public HashSet<String> getSpectators() + { + return getStartupSpectators(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java new file mode 100644 index 0000000..4f7a2a5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java @@ -0,0 +1,264 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.gui.teams.builder.TeamBuilderStepColorGUI; +import eu.carrade.amaury.UHCReloaded.gui.teams.editor.TeamEditGUI; +import eu.carrade.amaury.UHCReloaded.teams.TeamManager; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.ColorsUtils; +import fr.zcraft.zlib.components.gui.ExplorerGui; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.gui.PromptGui; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + + +public class TeamsSelectorGUI extends ExplorerGui<UHTeam> +{ + private final String TEAM_ITEM_TYPE; + private final boolean GLOW_ON_CURRENT_TEAM; + + private final TeamManager tm = UHCReloaded.get().getTeamManager(); + + public TeamsSelectorGUI() + { + TEAM_ITEM_TYPE = UHConfig.TEAMS_OPTIONS.CHEST_GUI.DISPLAY.TEAM_ITEM.get().toLowerCase(); + GLOW_ON_CURRENT_TEAM = UHConfig.TEAMS_OPTIONS.CHEST_GUI.DISPLAY.GLOW_ON_SELECTED_TEAM.get(); + } + + @Override + protected void onUpdate() + { + /// The title of the teams selector GUI. {0} = teams count. + setTitle(I.t("{black}Select a team {reset}({0})", tm.getTeams().size())); + setData(tm.getTeams().toArray(new UHTeam[tm.getTeams().size()])); + + setMode(Mode.READONLY); + setKeepHorizontalScrollingSpace(true); + + if (getPlayer().hasPermission("uh.player.renameTeam")) + { + int renameSlot = getPlayer().hasPermission("uh.team") ? getSize() - 6 : getSize() - 5; + + action("rename", renameSlot, GuiUtils.makeItem( + /// The title of a button to rename our team, in the selector GUI. + Material.BOOK_AND_QUILL, I.t("{white}Rename your team"), + /// Warning displayed in the "Rename your team" button, if the player is not in a team + tm.getTeamForPlayer(getPlayer()) == null ? GuiUtils.generateLore(I.t("{gray}You have to be in a team")) : null + )); + } + + if (getPlayer().hasPermission("uh.team")) + { + int newTeamSlot = getPlayer().hasPermission("uh.player.renameTeam") ? getSize() - 4 : getSize() - 5; + + /// The title of a button to create a new team, in the selector GUI. + action("new", newTeamSlot, GuiUtils.makeItem(Material.EMERALD, I.t("{white}New team"))); + } + } + + @Override + protected ItemStack getViewItem(UHTeam team) + { + final boolean playerInTeam = team.getPlayersUUID().contains(getPlayer().getUniqueId()); + + + // Lore + final List<String> lore = new ArrayList<>(); + + lore.add(""); + + if (team.getSize() != 0) + { + /// The "Players" title in the selector GUI, on a team's tooltip + lore.add(I.t("{blue}Players")); + for (OfflinePlayer player : team.getPlayers()) + { + /// An item of the players list in the selector GUI, on a team's tooltip + lore.add(I.t("{darkgray}- {white}{0}", player.getName())); + } + + lore.add(""); + } + + if (getPlayer().hasPermission("uh.player.join.self") && !playerInTeam) + { + if (!team.isFull()) + { + lore.add(I.t("{darkgray}» {white}Click {gray}to join this team")); + } + else + { + lore.add(I.t("{darkgray}» {red}This team is full")); + } + } + else if (getPlayer().hasPermission("uh.player.leave.self") && playerInTeam) + { + lore.add(I.t("{darkgray}» {white}Click {gray}to leave this team")); + } + + if (getPlayer().hasPermission("uh.team")) // TODO adapt with new granular permissions + { + lore.add(I.t("{darkgray}» {white}Right-click {gray}to manage this team")); + } + + + // Item + final ItemStack item; + final DyeColor dye = team.getColor() != null ? ColorsUtils.chat2Dye(team.getColor().toChatColor()) : DyeColor.WHITE; + + switch (TEAM_ITEM_TYPE) + { + case "banner": + item = team.getBanner(); + break; + + case "clay": + item = new ItemStack(Material.STAINED_CLAY, 1, dye.getWoolData()); + break; + + case "glass": + item = new ItemStack(Material.STAINED_GLASS_PANE, 1, dye.getWoolData()); + break; + + case "glass_pane": + item = new ItemStack(Material.STAINED_GLASS_PANE, 1, dye.getWoolData()); + break; + + case "dye": + item = new ItemStack(Material.INK_SACK, 1, dye.getDyeData()); + break; + + default: + item = new ItemStack(Material.WOOL, 1, dye.getWoolData()); + } + + + // Title + final String title = tm.getMaxPlayersPerTeam() != 0 + /// Title of the team item in the teams selector GUI (with max). {0}: team display name. {1}: players count. {2}: max count. + ? I.t("{white}Team {0} {gray}({1}/{2})", team.getDisplayName(), team.getSize(), tm.getMaxPlayersPerTeam()) + /// Title of the team item in the teams selector GUI (without max) {0}: team display name. {1}: players count. + : I.tn("{white}Team {0} {gray}({1} player)", "{white}Team {0} {gray}({1} players)", team.getSize(), team.getDisplayName(), team.getSize()); + + return new ItemStackBuilder(item) + .title(title) + .lore(lore) + .glow(GLOW_ON_CURRENT_TEAM && playerInTeam) + .hideAttributes() + .item(); + } + + @Override + protected ItemStack getEmptyViewItem() + { + return new ItemStackBuilder(Material.BARRIER) + .title(I.t("{red}No team created")) + .lore(getPlayer().hasPermission("uh.team") + /// Subtitle of the item displayed in the teams selector GUI if there isn't anything to display. + ? GuiUtils.generateLore(I.t("{gray}Click the emerald button below to create one.")) + /// Subtitle of the item displayed in the teams selector GUI if there isn't anything to display and the player cannot create a team. + : GuiUtils.generateLore(I.t("{gray}Wait for an administrator to create one."))) + .hideAttributes() + .item(); + } + + @Override + protected ItemStack getPickedUpItem(UHTeam team) + { + final boolean playerInTeam = team.getPlayersUUID().contains(getPlayer().getUniqueId()); + + if (getPlayer().hasPermission("uh.player.join.self") && !playerInTeam) + { + try + { + team.addPlayer(getPlayer()); + } + catch (RuntimeException ignored) {} // team full, does nothing + } + else if (getPlayer().hasPermission("uh.player.leave.self") && playerInTeam) + { + team.removePlayer(getPlayer()); + } + + update(); + return null; + } + + @Override + protected void onRightClick(UHTeam team) + { + if (getPlayer().hasPermission("uh.team")) // TODO adapt with new granular permissions + { + Gui.open(getPlayer(), new TeamEditGUI(team), this); + } + else + { + getPickedUpItem(team); + } + } + + @GuiAction ("rename") + public void rename() + { + final UHTeam team = tm.getTeamForPlayer(getPlayer()); + if (team == null) + return; + + Gui.open(getPlayer(), new PromptGui(new Callback<String>() { + @Override + public void call(String name) + { + team.setName(name); + } + }, team.getName()), this); + } + + @GuiAction ("new") + public void newTeam() + { + Gui.open(getPlayer(), new TeamBuilderStepColorGUI()); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java new file mode 100644 index 0000000..d23acc0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java @@ -0,0 +1,139 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.builder; + +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.utils.TextUtils; +import fr.zcraft.zlib.components.gui.ActionGui; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.Collections; + + +/** + * The base of the team creator GUIs: contains the breadcrumb generator. + */ +public abstract class TeamBuilderBaseGUI extends ActionGui +{ + protected void generateBreadcrumbs(BuildingStep step) + { + for (int i = 0; i < 9; i++) + { + if (i != 1 && i != 4 && i != 7) + { + action("", i, GuiUtils.makeItem(new ItemStack(Material.STAINED_GLASS_PANE, 1, DyeColor.WHITE.getWoolData()), ChatColor.RESET + " ", null)); + } + else + { + final BuildingStep slotStep; + final String achievedSubtitle; + + if (i == 1) + { + slotStep = BuildingStep.COLOR; + achievedSubtitle = getColor() != null ? (getColor() == TeamColor.RANDOM ? ChatColor.WHITE + "" + ChatColor.MAGIC + "Random color" : getColor().toChatColor() + TextUtils.friendlyEnumName(getColor())) : ""; + } + else if (i == 4) + { + slotStep = BuildingStep.NAME; + achievedSubtitle = getName() != null ? ChatColor.GRAY + getName() : ""; + } + else + { + slotStep = BuildingStep.PLAYERS; + achievedSubtitle = ""; // Never displayed as achieved: it's the last one. + } + + final boolean achieved = slotStep.isAchieved(step); + + action("", i, GuiUtils.makeItem( + new ItemStack(Material.STAINED_GLASS_PANE, 1, achieved ? DyeColor.LIME.getWoolData() : DyeColor.RED.getWoolData()), + slotStep.getName(), + achieved ? Collections.singletonList(achievedSubtitle) : null + )); + } + } + } + + /** + * @return the selected color. {@code null} if not selected yet. + */ + protected abstract TeamColor getColor(); + + /** + * @return the chosen name. {@code null} if not chosen yet. + */ + protected abstract String getName(); + + + /** + * The current step used by {@link #generateBreadcrumbs(BuildingStep)} + */ + protected enum BuildingStep + { + /// The title of the first step in the team creator GUIs + COLOR (I.t("{gray}1. {white}{bold}Team color")), + /// The title of the second step in the team creator GUIs + NAME (I.t("{gray}2. {white}{bold}Team name")), + /// The title of the third step in the team creator GUIs + PLAYERS (I.t("{gray}3. {white}{bold}Team members")); + + + private final String name; + + BuildingStep(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } + + /** + * Checks if this step is achieved, at the given step. + * + * @param step The current step. + * @return {@code true} if achieved. + */ + public boolean isAchieved(BuildingStep step) + { + return step.ordinal() > this.ordinal(); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java new file mode 100644 index 0000000..9b3d596 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java @@ -0,0 +1,148 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.builder; + +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.utils.ColorsUtils; +import eu.carrade.amaury.UHCReloaded.utils.TextUtils; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.runners.RunTask; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; + +import java.util.Random; + + +public class TeamBuilderStepColorGUI extends TeamBuilderBaseGUI +{ + private final Random randomSource = new Random(); + + private BukkitTask randomUpdate = null; + + + @Override + protected void onUpdate() + { + /// The title of the color selector GUI, in the create team GUIs + setTitle(I.t("New team » {black}Color")); + setSize(6 * 9); + + generateBreadcrumbs(BuildingStep.COLOR); + + insertColors(3); + } + + protected void insertColors(final int firstLine) + { + final int offset = (firstLine - 1) * 9; + + /// The random color button in a colors selector GUI. + action("random", offset + 4, GuiUtils.makeItem(Material.WOOL, I.t("{lightpurple}Random color"))); + + insertColor(offset + 10, ChatColor.WHITE); + insertColor(offset + 11, ChatColor.AQUA); + insertColor(offset + 12, ChatColor.BLUE); + insertColor(offset + 13, ChatColor.GREEN); + insertColor(offset + 14, ChatColor.YELLOW); + insertColor(offset + 15, ChatColor.GOLD); + insertColor(offset + 16, ChatColor.LIGHT_PURPLE); + + insertColor(offset + 19, ChatColor.RED); + insertColor(offset + 20, ChatColor.DARK_RED); + insertColor(offset + 21, ChatColor.DARK_GREEN); + insertColor(offset + 22, ChatColor.DARK_PURPLE); + insertColor(offset + 23, ChatColor.DARK_BLUE); + insertColor(offset + 24, ChatColor.DARK_AQUA); + insertColor(offset + 25, ChatColor.BLACK); + + insertColor(offset + 29, ChatColor.GRAY); + insertColor(offset + 33, ChatColor.DARK_GRAY); + + randomUpdate = RunTask.timer(new Runnable() + { + @Override + public void run() + { + ItemStack random = getInventory().getItem(offset + 4); + if (random != null) + random.setDurability((short) randomSource.nextInt(16)); + } + }, 15l, 15l); + } + + private void insertColor(int slot, ChatColor color) + { + action("", slot, GuiUtils.makeItem(new ItemStack(Material.WOOL, 1, ColorsUtils.chat2Dye(color).getWoolData()), color + TextUtils.friendlyEnumName(color), null)); + } + + + @GuiAction ("random") + protected void random() + { + saveColor(TeamColor.RANDOM); + } + + @Override + protected void unknown_action(String name, int slot, ItemStack item) + { + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) + saveColor(TeamColor.fromChatColor(ChatColor.getByChar(ChatColor.getLastColors(item.getItemMeta().getDisplayName()).substring(1)))); + } + + protected void saveColor(TeamColor color) + { + Gui.open(getPlayer(), new TeamBuilderStepNameGUI(color)); + } + + @Override + protected void onClose() + { + if (randomUpdate != null) + { + randomUpdate.cancel(); + randomUpdate = null; + } + + super.onClose(); + } + + @Override + protected TeamColor getColor() { return null; } + + @Override + protected String getName() { return null; } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java new file mode 100644 index 0000000..2faa1d0 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java @@ -0,0 +1,92 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.builder; + +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.gui.PromptGui; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import org.bukkit.Material; + + +public class TeamBuilderStepNameGUI extends TeamBuilderBaseGUI +{ + private final TeamColor color; + + public TeamBuilderStepNameGUI(TeamColor color) + { + this.color = color; + } + + @Override + protected void onUpdate() + { + /// The title of the name selector GUI, in the create team GUIs + setTitle(I.t("New team » {black}Name")); + setSize(6 * 9); + + generateBreadcrumbs(BuildingStep.NAME); + + action("name", 22, GuiUtils.makeItem( + Material.BOOK_AND_QUILL, + /// The title of the button opening the sign to write the team name (creator GUIs) + I.t("{white}Name the team"), + /// The legend of the button opening the sign to write the team name (creator GUIs) + GuiUtils.generateLore(I.t("{gray}When clicked, a sign will open; write the name of the team inside.")) + )); + } + + @GuiAction ("name") + protected void name() + { + Gui.open(getPlayer(), new PromptGui(new Callback<String>() { + @Override + public void call(String name) + { + if (name.trim().isEmpty()) + Gui.open(getPlayer(), new TeamBuilderStepNameGUI(getColor())); + else + Gui.open(getPlayer(), new TeamBuilderStepPlayersGUI(getColor(), name)); + } + })); + } + + + @Override + protected TeamColor getColor() { return color; } + + @Override + protected String getName() { return null; } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java new file mode 100644 index 0000000..0e1a13d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java @@ -0,0 +1,189 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.builder; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.gui.teams.TeamsSelectorGUI; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.OfflinePlayersComparator; +import eu.carrade.amaury.UHCReloaded.utils.TextUtils; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + + +public class TeamBuilderStepPlayersGUI extends TeamBuilderBaseGUI +{ + private final TeamColor color; + private final String name; + + private final Set<UUID> teamMembers = new HashSet<>(); + + + public TeamBuilderStepPlayersGUI(TeamColor color, String name) + { + this.color = color; + this.name = name; + } + + @Override + protected void onUpdate() + { + /// The title of the members selector GUI, in the create team GUIs + setTitle(I.t("New team » {black}Members")); + setSize(6 * 9); + + generateBreadcrumbs(BuildingStep.PLAYERS); + + + // Players + + Set<OfflinePlayer> players = new TreeSet<>(new OfflinePlayersComparator()); + players.addAll(OfflinePlayersLoader.getOfflinePlayers()); + + int slot = 9; + for (OfflinePlayer player : players) + { + action(player.getUniqueId().toString(), slot, generatePlayerButton(player)); + + if (slot < 44) slot++; + else break; + } + + + // Done button + + List<String> lore = new ArrayList<>(); + lore.add(""); + /// The summary title in the final « create the team » button of the create team GUIs + lore.add(I.t("{blue}{bold}Summary")); + /// The team name in the final « create the team » button of the create team GUIs + lore.add(I.t("{gray}Team name: {white}{0}", getName())); + /// The team color in the final « create the team » button of the create team GUIs + lore.add(I.t("{gray}Color: {0}", getColor() == TeamColor.RANDOM ? ChatColor.MAGIC + "Random" : getColor().toChatColor() + TextUtils.friendlyEnumName(getColor()))); + /// The team members count in the final « create the team » button of the create team GUIs + lore.add(I.t("{gray}Members: {white}{0}", teamMembers.size())); + lore.add(""); + for (UUID teamMember : teamMembers) + { + OfflinePlayer player = Bukkit.getOfflinePlayer(teamMember); + /// A member bullet in the final « create the team » button of the create team GUIs + lore.add(I.t("{darkgray}- {white}{0}", player != null ? player.getName() : teamMember)); + } + + /// The title of the final « create the team » button of the create team GUIs + action("done", getSize() - 5, GuiUtils.makeItem(Material.EMERALD, I.t("{green}Create the team"), lore)); + } + + private ItemStack generatePlayerButton(OfflinePlayer player) + { + ItemStack button = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); + SkullMeta meta = (SkullMeta) button.getItemMeta(); + + String displayName = player instanceof Player ? ((Player) player).getDisplayName() : player.getName(); + UHTeam team = UHCReloaded.get().getTeamManager().getTeamForPlayer(player); + + meta.setOwner(player.getName()); + /// The title of a button to select a player (a skull button). {0} = player's display name. + meta.setDisplayName(I.t("{reset}{0}", displayName)); + meta.setLore(Arrays.asList( + player.isOnline() ? I.t("{gray}Online") : I.t("{gray}Offline"), + team != null ? I.t("{gray}Current team: {0}", team.getDisplayName()) : I.t("{gray}Current team: none"), + "", + teamMembers.contains(player.getUniqueId()) ? I.t("{lightpurple}Selected!") : I.t("{darkgray}» {white}Click {gray}to add to the team") + )); + + button.setItemMeta(meta); + return button; + } + + + @Override + protected void unknown_action(String name, int slot, ItemStack item) + { + UUID playerUUID; + try { playerUUID = UUID.fromString(name); } catch(IllegalArgumentException e) { return; } + + if (teamMembers.contains(playerUUID)) + teamMembers.remove(playerUUID); + else + teamMembers.add(playerUUID); + + update(); + } + + @GuiAction ("done") + protected void done() + { + UHTeam team = new UHTeam(getName(), getColor()); + + try + { + UHCReloaded.get().getTeamManager().addTeam(team); + getPlayer().sendMessage(I.t("{cs}Team created.")); + + for (UUID member : teamMembers) team.addPlayer(OfflinePlayersLoader.getOfflinePlayer(member)); + } + catch (IllegalArgumentException e) + { + getPlayer().sendMessage(I.t("{ce}This team already exists.")); + } + + Gui.open(getPlayer(), new TeamsSelectorGUI()); + } + + + @Override + protected TeamColor getColor() { return color; } + + @Override + protected String getName() { return name; } + +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java new file mode 100644 index 0000000..92a432a --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java @@ -0,0 +1,79 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.editor; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.gui.ActionGui; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + + +public abstract class TeamActionGUI extends ActionGui +{ + protected final UHTeam team; + + public TeamActionGUI(UHTeam team) + { + this.team = team; + } + + /** + * Checks if the team still exists. + * @return {@code true} if the team exists. + */ + protected boolean exists() + { + return UHCReloaded.get().getTeamManager().isTeamRegistered(team); + } + + /** + * Generates the item to display if the team was deleted while a player edited the team on a GUI. + * @return the item. + */ + protected ItemStack getDeletedItem() + { + return new ItemStackBuilder(Material.BARRIER) + /// Title of the item displayed if a team was deleted while someone edited it in a GUI. + .title(I.t("{red}Team deleted")) + /// Lore of the item displayed if a team was deleted while someone edited it in a GUI. + .lore(GuiUtils.generateLore(I.t("{gray}The team {0}{gray} was deleted by another player.", team.getDisplayName()))) + .lore("") + /// Lore of the item displayed if a team was deleted while someone edited it in a GUI. + .lore(GuiUtils.generateLore(I.t("{gray}Press {white}Escape{gray} to go back to the teams list."))) + .hideAttributes() + .item(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java new file mode 100644 index 0000000..7eee0e9 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java @@ -0,0 +1,65 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.editor; + +import eu.carrade.amaury.UHCReloaded.gui.teams.builder.TeamBuilderStepColorGUI; +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.i18n.I; + + +public class TeamEditColorGUI extends TeamBuilderStepColorGUI +{ + private final UHTeam team; + + public TeamEditColorGUI(UHTeam team) + { + this.team = team; + } + + @Override + protected void onUpdate() + { + /// The title of the edit team color GUI. {0} = team name (raw). + setTitle(I.t("{0} » {black}Color", team.getName())); + setSize(6 * 9); + insertColors(2); + } + + @Override + protected void saveColor(TeamColor color) + { + team.setColor(color); + Gui.open(getPlayer(), new TeamEditGUI(team), getParent().getParent()); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java new file mode 100644 index 0000000..0a6910d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java @@ -0,0 +1,103 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.editor; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.gui.teams.TeamsSelectorGUI; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + + +public class TeamEditDeleteGUI extends TeamActionGUI +{ + public TeamEditDeleteGUI(UHTeam team) + { + super(team); + } + + + @Override + protected void onUpdate() + { + /// The title of the delete team GUI. {0} = team name (raw). + setTitle(I.t("{0} » {darkred}Delete", team.getName())); + setSize(9); + + if (!exists()) + { + action("", 4, getDeletedItem()); + return; + } + + for (int slot = 0; slot < 3; slot++) + { + action("keep", slot, GuiUtils.makeItem( + new ItemStack(Material.STAINED_GLASS_PANE, 1, DyeColor.LIME.getWoolData()), + /// The title of the "keep" button in the delete team GUI + I.t("{green}Keep this team alive"), + null + )); + } + + action("", 4, team.getBanner()); + + for (int slot = 6; slot < 9; slot++) + { + action("delete", slot, GuiUtils.makeItem( + new ItemStack(Material.STAINED_GLASS_PANE, 1, DyeColor.RED.getWoolData()), + /// The title of the "delete" button in the delete team GUI + I.t("{red}Delete this team {italic}forever"), + null + )); + } + } + + + @GuiAction ("keep") + protected void keep() + { + close(); + } + + @GuiAction ("delete") + protected void delete() + { + UHCReloaded.get().getTeamManager().removeTeam(team); + Gui.open(getPlayer(), new TeamsSelectorGUI()); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java new file mode 100644 index 0000000..6a5f106 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java @@ -0,0 +1,182 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.editor; + +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.ColorsUtils; +import eu.carrade.amaury.UHCReloaded.utils.TextUtils; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.gui.PromptGui; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.Callback; +import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + + +public class TeamEditGUI extends TeamActionGUI +{ + public TeamEditGUI(UHTeam team) + { + super(team); + } + + + @Override + protected void onUpdate() + { + /// The title of the edit team GUI. {0} = team display name. + setTitle(I.t("Teams » {black}{0}", team.getDisplayName())); + setSize(36); + + if (!exists()) + { + action("", 13, getDeletedItem()); + return; + } + + // Banner + action("banner", 9, new ItemStackBuilder(team.getBanner()) + .title(team.getDisplayName()) + /// Members count in the banner description, in the team edit GUI. + .lore(GuiUtils.generateLore(I.tn("{white}{0} {gray}member", "{white}{0} {gray}members", team.getSize(), team.getSize()))) + .lore(" ") + .lore(GuiUtils.generateLore(I.t("{white}Click with a banner {gray}to update this team's banner"))) + .hideAttributes() + ); + + // Color + action("color", 11, GuiUtils.makeItem( + new ItemStack(Material.WOOL, 1, ColorsUtils.chat2Dye(team.getColor().toChatColor()).getWoolData()), + /// Update team color button in edit GUI. + I.t("{green}Update the color"), + /// Current team color in edit GUI. {0} = formatted color name. + GuiUtils.generateLore(I.tc("current_team_color", "{gray}Current: {white}{0}", team.getColor().toChatColor() + TextUtils.friendlyEnumName(team.getColor()))) + )); + + // Name + action("name", 13, GuiUtils.makeItem( + Material.BOOK_AND_QUILL, + /// Rename team button in edit GUI. + I.t("{green}Rename the team"), + /// Current team name in edit GUI. {0} = raw team name. + GuiUtils.generateLore(I.tc("current_team_name", "{gray}Current: {white}{0}", team.getName())) + )); + + // Members + List<String> lore = new ArrayList<>(); + for (OfflinePlayer player : team.getPlayers()) + if (player.isOnline()) + lore.add(I.t("{green} • ") + ChatColor.RESET + player.getName()); + else + lore.add(I.t("{red} • ") + ChatColor.RESET + player.getName()); + + action("members", 15, GuiUtils.makeItem( + new ItemStack(Material.SKULL_ITEM, 1, (short) 3), + /// Update team members button in edit GUI. + I.t("{green}Add or remove players"), + lore + )); + + // Delete + action("delete", 17, GuiUtils.makeItem( + Material.BARRIER, + /// Delete team button in edit GUI. + I.t("{red}Delete this team"), + /// Warning under the "delete team" button title. + GuiUtils.generateLore(I.t("{gray}Cannot be undone")) + )); + + // Exit + action("exit", getSize() - 5, GuiUtils.makeItem( + Material.EMERALD, + /// Go back button in GUIs. + I.t("{green}« Go back") + )); + } + + + @GuiAction ("banner") + protected void banner(InventoryClickEvent ev) + { + if (ev.getCursor() != null && ev.getCursor().getType() == Material.BANNER) + { + team.setBanner(ev.getCursor()); + update(); + } + } + + @GuiAction ("color") + protected void color() + { + Gui.open(getPlayer(), new TeamEditColorGUI(team), this); + } + + @GuiAction ("name") + protected void name() + { + Gui.open(getPlayer(), new PromptGui(new Callback<String>() { + @Override + public void call(String name) + { + if (!name.trim().isEmpty()) + team.setName(name); + } + }, team.getName()), this); + } + + @GuiAction ("members") + protected void members() + { + Gui.open(getPlayer(), new TeamEditMembersGUI(team), this); + } + + @GuiAction ("delete") + protected void delete() + { + Gui.open(getPlayer(), new TeamEditDeleteGUI(team), this); + } + + @GuiAction ("exit") + protected void exit() + { + close(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java new file mode 100644 index 0000000..cbbe126 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java @@ -0,0 +1,123 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.gui.teams.editor; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.OfflinePlayersComparator; +import fr.zcraft.zlib.components.gui.ExplorerGui; +import fr.zcraft.zlib.components.gui.GuiAction; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; + + +public class TeamEditMembersGUI extends ExplorerGui<OfflinePlayer> +{ + private final UHTeam team; + + public TeamEditMembersGUI(UHTeam team) + { + this.team = team; + } + + + @Override + protected void onUpdate() + { + /// The title of the edit team members GUI. {0} = team name (raw). + setTitle(I.t("{0} » {black}Members", team.getName())); + setKeepHorizontalScrollingSpace(true); + + Set<OfflinePlayer> players = new TreeSet<>(new OfflinePlayersComparator()); + players.addAll(OfflinePlayersLoader.getOfflinePlayers()); + setData(players.toArray(new OfflinePlayer[players.size()])); + + action("back", getSize() - 5, GuiUtils.makeItem( + Material.EMERALD, + I.t("{green}« Go back") + )); + } + + @Override + protected ItemStack getViewItem(OfflinePlayer player) + { + ItemStack button = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); + SkullMeta meta = (SkullMeta) button.getItemMeta(); + + String displayName = player instanceof Player ? ((Player) player).getDisplayName() : player.getName(); + UHTeam team = UHCReloaded.get().getTeamManager().getTeamForPlayer(player); + + Boolean inThisTeam = this.team.equals(team); + + meta.setOwner(player.getName()); + /// The title of a button to select a player (a skull button). {0} = player's display name. + meta.setDisplayName(I.t("{reset}{0}", displayName)); + meta.setLore(Arrays.asList( + player.isOnline() ? I.t("{gray}Online") : I.t("{gray}Offline"), + team != null ? I.t("{gray}Current team: {0}", team.getDisplayName()) : I.t("{gray}Current team: none"), + "", + inThisTeam ? I.t("{darkgray}» {white}Click {gray}to remove this player") : I.t("{darkgray}» {white}Click {gray}to add this player") + )); + + button.setItemMeta(meta); + return button; + } + + @Override + protected ItemStack getPickedUpItem(OfflinePlayer player) + { + if (team.containsPlayer(player.getUniqueId())) + team.removePlayer(player); + else + team.addPlayer(player); + + update(); + + return null; + } + + @GuiAction ("back") + protected void back() + { + close(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java new file mode 100644 index 0000000..598642c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java @@ -0,0 +1,402 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.integration; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.teams.TeamColor; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.dynmap.DynmapAPI; +import org.dynmap.markers.Marker; +import org.dynmap.markers.MarkerAPI; +import org.dynmap.markers.MarkerIcon; +import org.dynmap.markers.MarkerSet; + + +public class UHDynmapIntegration +{ + private UHCReloaded p = null; + private DynmapAPI api = null; + private MarkerAPI markerAPI = null; + private MarkerSet markerSet = null; + + public UHDynmapIntegration(UHCReloaded plugin) + { + this.p = plugin; + + Plugin apiTest = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); + if (apiTest == null || !apiTest.isEnabled()) + { + PluginLogger.warning("Dynmap is not present, so the integration was disabled."); + return; + } + + this.api = (DynmapAPI) apiTest; + + markerAPI = api.getMarkerAPI(); + if (markerAPI == null) + { + PluginLogger.warning("Dynmap is available, but the markers API is not. The integration was disabled."); + return; + } + + + // All is good, let's integrate. + initDynmapIntegration(); + + PluginLogger.info("Successfully hooked into Dynmap."); + } + + private void initDynmapIntegration() + { + + markerSet = markerAPI.getMarkerSet("uhplugin.markerset"); + + if (markerSet == null) + { + markerSet = markerAPI.createMarkerSet("uhplugin.markerset", "UltraHardcore", null, false); + } + else + { + markerSet.setMarkerSetLabel("UltraHardcore"); + } + } + + public void shutdownDynmapIntegration() + { + if (isDynmapIntegrationEnabled()) + { + markerSet.deleteMarkerSet(); + } + } + + public boolean isDynmapIntegrationEnabled() + { + return !(this.api == null); + } + + public DynmapAPI getDynmapAPI() + { + return api; + } + + public MarkerAPI getDynmapMarkerAPI() + { + return markerAPI; + } + + /** Death locations **/ + + /** + * Displays the death location of the given player. + * + * @param player The player. + */ + public void showDeathLocation(Player player) + { + if (!isDynmapIntegrationEnabled()) + { + return; + } + + if (!UHConfig.DYNMAP.SHOW_DEATH_LOCATIONS.get()) + { + return; + } + + if (!p.getGameManager().hasDeathLocation(player)) + { + return; + } + + Location deathPoint = p.getGameManager().getDeathLocation(player); + + String markerID = getDeathMarkerName(player); + /// Dynmap marker label of a death point + String markerLabel = I.t("Death point of {0}", player.getName()); + MarkerIcon icon = markerAPI.getMarkerIcon("skull"); + + Marker marker = markerSet.createMarker(markerID, markerLabel, true, deathPoint.getWorld().getName(), deathPoint.getX(), deathPoint.getY(), deathPoint.getZ(), icon, false); + if (marker == null) + { + p.getLogger().warning("Unable to create marker " + markerID); + } + } + + /** + * Hides the death location of the given player. + * + * @param player The player. + */ + public void hideDeathLocation(Player player) + { + if (!isDynmapIntegrationEnabled()) + { + return; + } + + if (!p.getConfig().getBoolean("dynmap.showDeathLocations")) + { + return; + } + + Marker marker = markerSet.findMarker(getDeathMarkerName(player)); + if (marker != null) + { + marker.deleteMarker(); + } + } + + /** + * Returns the internal ID of the marker of the death point of the given player. + * + * @param player The player. + * @return The ID. + */ + private String getDeathMarkerName(Player player) + { + return "uhplugin.death." + player.getName(); + } + + + /** Spawn locations **/ + + /** + * Displays the spawn point of the given team. + * + * @param team The team. + * @param spawnPoint The location of the spawn point. + */ + public void showSpawnLocation(UHTeam team, Location spawnPoint) + { + if (!isDynmapIntegrationEnabled()) + { + return; + } + + if (!UHConfig.DYNMAP.SHOW_SPAWN_LOCATIONS.get()) + { + return; + } + + + TeamColor teamColor = team.getColor(); + if (teamColor == null) + { + teamColor = TeamColor.GREEN; // green flags for solo games without colors + } + + String markerID = getSpawnMarkerName(team); + + String markerLabel; + if (p.getGameManager().isGameWithTeams()) + { + /// Dynmap marker label of a spawn point of a team. + markerLabel = I.t("Spawn point of the team {0}", team.getName()); + } + else + { + /// Dynmap marker label of a spawn point of a player, in solo. + markerLabel = I.t("Spawn point of {0}", team.getName()); + } + + showSpawnLocation(spawnPoint, teamColor, markerLabel, markerID); + } + + /** + * Displays the spawn point of the given player. + * + * <p> + * Used when the teleportation ignores the teams. + * </p> + * + * @param player The player. + * @param spawnPoint The location of the spawn point. + */ + public void showSpawnLocation(OfflinePlayer player, Location spawnPoint) + { + if (player == null) return; + + UHTeam team = p.getTeamManager().getTeamForPlayer(player); + + showSpawnLocation(player, team != null ? team.getColor() : null, spawnPoint); + } + + /** + * Displays the spawn point of the given player. + * + * <p> + * Used when the teleportation ignores the teams. + * </p> + * + * @param player The player. + * @param color The color of the spawn point (i.e. of the team). + * @param spawnPoint The location of the spawn point. + */ + public void showSpawnLocation(OfflinePlayer player, TeamColor color, Location spawnPoint) + { + if (!isDynmapIntegrationEnabled()) + { + return; + } + + if (!UHConfig.DYNMAP.SHOW_SPAWN_LOCATIONS.get()) + { + return; + } + + + if (color == null) + { + color = TeamColor.GREEN; + } + + String markerID = getSpawnMarkerName(player); + + /// Dynmap marker label of a spawn point of a player, when the teleportation ignores the teams. + String markerLabel = I.t("Spawn point of {0}", player.getName()); + + showSpawnLocation(spawnPoint, color, markerLabel, markerID); + } + + /** + * Displays a spawn-point marker. + * + * @param spawnPoint The location of the spawn. + * @param color The color of the team (for the flag). + * @param label The label of the marker. + * @param markerID The ID of the marker. + */ + private void showSpawnLocation(Location spawnPoint, TeamColor color, String label, String markerID) + { + + /* *** Icon *** */ + + MarkerIcon icon; + + // Let's try to find the best icon + // Available flags: + // redflag, orangeflag, yellowflag, greenflag, blueflag, purpleflag, pinkflag, pirateflag (black) + // Ref. https://github.com/webbukkit/dynmap/wiki/Using-markers + + switch (color) + { + case BLUE: + case DARK_BLUE: + case AQUA: + case DARK_AQUA: + icon = markerAPI.getMarkerIcon("blueflag"); + break; + + case GREEN: + case DARK_GREEN: + icon = markerAPI.getMarkerIcon("greenflag"); + break; + + case GOLD: + icon = markerAPI.getMarkerIcon("orangeflag"); + break; + + case YELLOW: + icon = markerAPI.getMarkerIcon("yellowflag"); + break; + + case RED: + case DARK_RED: + icon = markerAPI.getMarkerIcon("redflag"); + break; + + case DARK_PURPLE: + icon = markerAPI.getMarkerIcon("purpleflag"); + break; + + case LIGHT_PURPLE: + icon = markerAPI.getMarkerIcon("pinkflag"); + break; + + case BLACK: + case DARK_GRAY: + case GRAY: + icon = markerAPI.getMarkerIcon("pirateflag"); + break; + + case WHITE: // There is nothing better than pink I think... + default: + icon = markerAPI.getMarkerIcon("pinkflag"); + break; + } + + + /* *** Registration *** */ + + Marker marker = markerSet.createMarker(markerID, label, true, spawnPoint.getWorld().getName(), spawnPoint.getX(), spawnPoint.getY(), spawnPoint.getZ(), icon, false); + + if (marker == null) + { + PluginLogger.warning("Unable to create marker {0}", markerID); + } + } + + /** + * Returns the internal ID of the marker of the spawn point of the given team. + * + * @param team The team. + * @return The ID. + */ + private String getSpawnMarkerName(UHTeam team) + { + return "uhplugin.spawn." + team.getName(); + } + + /** + * Returns the internal ID of the marker of the spawn point of the given team. + * + * <p> + * Used if the teleportation ignores the teams. + * </p> + * + * @param player The player. + * @return The ID. + */ + private String getSpawnMarkerName(OfflinePlayer player) + { + return "uhplugin.spawn." + player.getName(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegration.java b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegration.java new file mode 100644 index 0000000..e94d114 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegration.java @@ -0,0 +1,60 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.integration; + +import com.comphenix.protocol.ProtocolLibrary; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.listeners.PacketsListener; +import fr.zcraft.zlib.tools.PluginLogger; + + +public class UHProtocolLibIntegration +{ + public UHProtocolLibIntegration(UHCReloaded p) + { + PacketsListener packetsListener = new PacketsListener(p); + + if (UHConfig.HARDCORE_HEARTS.DISPLAY.get()) + { + ProtocolLibrary.getProtocolManager().addPacketListener(packetsListener); + } + + if (UHConfig.AUTO_RESPAWN.DO.get()) + { + p.getServer().getPluginManager().registerEvents(packetsListener, p); + } + + PluginLogger.info("Successfully hooked into ProtocolLib."); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegrationWrapper.java b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegrationWrapper.java new file mode 100644 index 0000000..1e2d8c1 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHProtocolLibIntegrationWrapper.java @@ -0,0 +1,125 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.integration; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import fr.zcraft.zlib.components.configuration.ConfigurationItem; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + +import java.util.ArrayList; +import java.util.List; + + +public class UHProtocolLibIntegrationWrapper +{ + + private UHCReloaded p = null; + private UHProtocolLibIntegration integration = null; + + public UHProtocolLibIntegrationWrapper(UHCReloaded p) + { + this.p = p; + + // Needed to avoid a NoClassDefFoundError. + // I don't like this way of doing this, but else, the plugin will not load without ProtocolLib. + + Plugin pl = Bukkit.getServer().getPluginManager().getPlugin("ProtocolLib"); + if (pl != null && pl.isEnabled()) + { + try + { + integration = new UHProtocolLibIntegration(p); + } + catch (NoClassDefFoundError e) + { + PluginLogger.error("ProtocolLib is present but cannot be loaded (outdated?), so the integration was disabled.", e); + } + } + else + { + PluginLogger.warning("ProtocolLib is not present, so the integration was disabled."); + } + } + + /** + * Returns true if ProtocolLib is installed and integrated into the plugin. + */ + public boolean isProtocolLibIntegrationEnabled() + { + return (this.integration != null); + } + + /** + * Checks if there are some enabled option which require ProtocolLib. + * + * @return A list of enabled options which requires ProtocolLib, or null + * if there isn't any enabled option that requires ProtocolLib. + */ + public List<String> isProtocolLibNeeded() + { + + ArrayList<ConfigurationItem<Boolean>> options = new ArrayList<>(); + options.add(UHConfig.HARDCORE_HEARTS.DISPLAY); + options.add(UHConfig.AUTO_RESPAWN.DO); + + ArrayList<String> enabledOptions = new ArrayList<>(); + + for (ConfigurationItem<Boolean> option : options) + { + if (option.get()) + { + enabledOptions.add(option.getFieldName()); + } + } + + if (enabledOptions.size() != 0) + { + return enabledOptions; + } + else + { + return null; + } + } + + /** + * Returns the wrapped integration. + */ + public UHProtocolLibIntegration getIntegration() + { + return integration; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHSpectatorPlusIntegration.java b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHSpectatorPlusIntegration.java new file mode 100644 index 0000000..d53cb42 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHSpectatorPlusIntegration.java @@ -0,0 +1,117 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.integration; + +import com.pgcraft.spectatorplus.SpectateAPI; +import com.pgcraft.spectatorplus.SpectatorPlus; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + + +public class UHSpectatorPlusIntegration +{ + + private UHCReloaded p = null; + private SpectatorPlus sp = null; + private SpectateAPI spAPI = null; + + public UHSpectatorPlusIntegration(UHCReloaded p) + { + this.p = p; + + Plugin spTest = Bukkit.getServer().getPluginManager().getPlugin("SpectatorPlus"); + if (spTest == null || !spTest.isEnabled()) + { + this.p.getLogger().warning("SpectatorPlus is not present, so the integration was disabled."); + return; + } + + this.sp = (SpectatorPlus) spTest; + + + try + { + Class.forName("com.pgcraft.spectatorplus.SpectateAPI"); + + if (sp.getDescription().getVersion().equals("1.9.1")) + { + // The API of SpectatorPlus 1.9.1 was not working. + throw new ClassNotFoundException(); + } + } + catch (ClassNotFoundException e) + { + PluginLogger.warning("SpectatorPlus is available, but the version you are using is too old."); + PluginLogger.warning("This plugin is tested and works with SpectatorPlus 1.9.2 or later. The SpectateAPI is needed."); + + this.sp = null; + return; + } + + + // All is OK, let's integrate. + try + { + spAPI = sp.getAPI(); + + PluginLogger.info("Successfully hooked into SpectatorPlus."); + } + + // Generic catch block to catch any kind of exception (logged, anyway), including e.g. + // NoSuchMethodError, if the API change, so the plugin is not broken. + catch (Throwable e) + { + PluginLogger.error("Cannot hook into SpectatorPlus, is this version compatible?", e); + + spAPI = null; + sp = null; + } + } + + public boolean isSPIntegrationEnabled() + { + return !(this.sp == null); + } + + public SpectatorPlus getSP() + { + return this.sp; + } + + public SpectateAPI getSPAPI() + { + return this.spAPI; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHWorldBorderIntegration.java b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHWorldBorderIntegration.java new file mode 100644 index 0000000..ac77862 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHWorldBorderIntegration.java @@ -0,0 +1,82 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.integration; + +import com.wimbli.WorldBorder.WorldBorder; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; + + +public class UHWorldBorderIntegration +{ + private WorldBorder wb = null; + + public UHWorldBorderIntegration() + { + Plugin wbTest = Bukkit.getServer().getPluginManager().getPlugin("WorldBorder"); + if (wbTest == null || !wbTest.isEnabled()) + { + PluginLogger.warning("WorldBorder is not present, so the integration was disabled."); + return; + } + + this.wb = (WorldBorder) wbTest; + + try + { + Class.forName("com.wimbli.WorldBorder.BorderData"); + Class.forName("com.wimbli.WorldBorder.Config"); + } + catch (ClassNotFoundException e) + { + PluginLogger.warning("WorldBorder is available, but the version you are using is too old."); + PluginLogger.warning("This plugin is tested and works with WorldBorder 1.8.0 or later."); + + this.wb = null; + return; + } + + PluginLogger.info("Successfully hooked into WorldBorder."); + } + + public boolean isWBIntegrationEnabled() + { + return !(this.wb == null); + } + + public WorldBorder getWorldBorder() + { + return wb; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java new file mode 100644 index 0000000..a9ba7f5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java @@ -0,0 +1,195 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.events.UHGameStartsEvent; +import eu.carrade.amaury.UHCReloaded.gui.teams.TeamsSelectorGUI; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.core.ZLib; +import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.permissions.Permissible; + + +public class BeforeGameListener implements Listener +{ + /** + * @param player A player + * @return True if an inventory action should not be done because he is a builder. + */ + private boolean excludeBuilder(Permissible player) + { + return UHConfig.BEFORE_START.INVENTORY.ALLOW_FOR_BUILDERS.get() && player.hasPermission("uh.build"); + } + + /** + * Opens the teams selector GUI, if needed (enabled, game not started, needed item). + * + * TODO improve selector item detection. + * + * @param player The player who right-clicked an item. + * @param item The right-clicked item. + */ + private void openTeamsGUI(Player player, ItemStack item) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + + if (UHConfig.BEFORE_START.TEAM_SELECTOR.ENABLED.get() + && item != null + && item.getType() == UHConfig.BEFORE_START.TEAM_SELECTOR.ITEM.get()) + { + Gui.open(player, new TeamsSelectorGUI()); + } + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent ev) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + + final boolean builder = excludeBuilder(ev.getPlayer()); + + if (!builder && UHConfig.BEFORE_START.INVENTORY.CLEAR.get()) + { + ev.getPlayer().getInventory().clear(); + ev.getPlayer().getInventory().setArmorContents(null); + } + + if (UHConfig.BEFORE_START.TEAM_SELECTOR.ENABLED.get()) + { + Material itemType = UHConfig.BEFORE_START.TEAM_SELECTOR.ITEM.get(); + + ItemStack item = new ItemStackBuilder(itemType) + /// The title of the item given before the game to select a team + .title(I.t("{green}{bold}Select a team {gray}(Right-Click)")) + /// The lore of the item given before the game to select a team + .lore(GuiUtils.generateLore(I.t("{gray}Right-click to select your team for this game"))) + .hideAttributes() + .item(); + + final ItemStack centralItem = ev.getPlayer().getInventory().getItem(4); + if (!builder || centralItem == null || centralItem.getType() == org.bukkit.Material.AIR) + ev.getPlayer().getInventory().setItem(4, item); + } + + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + { + UHCReloaded.get().getTeamManager().displayTeamInActionBar(ev.getPlayer()); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerInteract(PlayerInteractEvent ev) + { + if (ev.getAction() != Action.PHYSICAL) + openTeamsGUI(ev.getPlayer(), ev.getItem()); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent ev) + { + openTeamsGUI(ev.getPlayer(), ev.getPlayer().getItemInHand()); + } + + @EventHandler + public void onPlayerClick(InventoryClickEvent ev) + { + if (UHConfig.BEFORE_START.INVENTORY.PREVENT_USAGE.get()) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + if (excludeBuilder(ev.getWhoClicked())) return; + if (!ev.getInventory().equals(ev.getWhoClicked().getInventory())) return; + + ev.setCancelled(true); + } + } + + @EventHandler + public void onPlayerDrag(InventoryDragEvent ev) + { + if (UHConfig.BEFORE_START.INVENTORY.PREVENT_USAGE.get()) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + if (excludeBuilder(ev.getWhoClicked())) return; + if (!ev.getInventory().equals(ev.getWhoClicked().getInventory())) return; + + ev.setCancelled(true); + } + } + + @EventHandler + public void onPlayerDrop(PlayerDropItemEvent ev) + { + if (UHConfig.BEFORE_START.INVENTORY.PREVENT_USAGE.get()) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + if (excludeBuilder(ev.getPlayer())) return; + + ev.setCancelled(true); + } + } + + @EventHandler + public void onPlayerPickup(PlayerPickupItemEvent ev) + { + if (UHCReloaded.get().getGameManager().isGameStarted()) return; + if (excludeBuilder(ev.getPlayer())) return; + + if (UHConfig.BEFORE_START.INVENTORY.PREVENT_USAGE.get()) + { + ev.setCancelled(true); + } + } + + @EventHandler + public void onGameStarts(UHGameStartsEvent ev) + { + ZLib.unregisterEvents(this); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java new file mode 100644 index 0000000..776b843 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java @@ -0,0 +1,396 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.protips.ProTips; +import eu.carrade.amaury.UHCReloaded.recipes.RecipesManager; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.runners.RunTask; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Banner; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event.Result; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.inventory.InventoryType.SlotType; +import org.bukkit.event.inventory.PrepareItemCraftEvent; +import org.bukkit.inventory.AnvilInventory; +import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.inventory.meta.BlockStateMeta; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.HashSet; + + +public class CraftingListener implements Listener +{ + private UHCReloaded p = null; + + public CraftingListener(UHCReloaded p) + { + this.p = p; + } + + + /** + * Used to: + * - prevent items to be crafted; + * - send a ProTip containing the craft to use, if an error occurred; + * - add a lure to the golden apples crafted from a head; + * - keep the name of the item when the anti-lore craft is used. + */ + @EventHandler + public void onPreCraftEvent(PrepareItemCraftEvent ev) + { + Recipe recipe = ev.getRecipe(); + + if (recipe == null) + { + return; + } + + /** Prevents items to be crafted **/ + + if (!p.getRecipesManager().isRecipeAllowed(recipe)) + { + ev.getInventory().setResult(new ItemStack(Material.AIR)); + + // ProTips + final String failedRecipe = p.getRecipesManager().getLastFailedRecipe(); + final Player player = (Player) ev.getViewers().get(0); // crafting inventory: only one viewer in all cases. + RunTask.later(new Runnable() + { + @Override + public void run() + { + switch (failedRecipe) + { + case RecipesManager.RECIPE_COMPASS: + switch (p.getRecipesManager().getCompassRecipeType()) + { + case RecipesManager.COMPASS_EASY: + ProTips.CRAFT_COMPASS_EASY.sendTo(player); + break; + case RecipesManager.COMPASS_MEDIUM: + ProTips.CRAFT_COMPASS_MEDIUM.sendTo(player); + break; + case RecipesManager.COMPASS_HARD: + ProTips.CRAFT_COMPASS_HARD.sendTo(player); + break; + } + + break; + + case RecipesManager.RECIPE_GLISTERING_MELON: + ProTips.CRAFT_GLISTERING_MELON.sendTo(player); + break; + + case RecipesManager.RECIPE_ENCHANTED_GOLDEN_APPLE: + ProTips.CRAFT_NO_ENCHANTED_GOLDEN_APPLE.sendTo(player); + break; + } + } + }, 40L); + + return; + } + + + /** Adds a lore to the golden apples crafted from a head **/ + + ItemStack loreResult = p.getRecipesManager().addLore(recipe, ev.getInventory()); + if (loreResult != null) + { + ev.getInventory().setResult(loreResult); + return; + } + + + /** The lore remover don't change the name of the item **/ + + ItemStack keepNameResult = p.getRecipesManager().keepNameOnLoreRemover(recipe, ev.getInventory()); + if (keepNameResult != null) + { + ev.getInventory().setResult(keepNameResult); + return; + } + } + + + /** + * - Workaround to fix the crafting grid being not updated when the item is taken + * from the grid. + * <p> + * - Prevents an apple to be renamed to/from the name of an head apple. + * + * (In vanilla clients, it is not possible to rename an apple to that name because of the + * ChatColor.RESET before, but some modded clients allows the player to write §r.) + * + * (Thanks to Zelnehlun on BukkitDev.) + * <p> + * - Crafts the special compass (“semi-shapeless” recipe). + */ + @EventHandler (ignoreCancelled = true) + public void onInventoryClick(final InventoryClickEvent ev) + { + // Just in case + if (ev.getWhoClicked() instanceof Player) + { + final Inventory inventory = ev.getInventory(); + + /** Workaround to fix the crafting grid being not updated when the item is taken + from the grid. **/ + if (inventory instanceof CraftingInventory && ev.getSlotType() == SlotType.RESULT) + { + p.getServer().getScheduler().runTaskLater(p, new Runnable() + { + + @Override + public void run() + { + for (HumanEntity viewer : ev.getViewers()) + { + if (viewer instanceof Player) + { + ((Player) viewer).updateInventory(); + } + } + } + }, 1L); + } + + + /** Allows any shape for the loots in the compass recipe. **/ + + if (inventory instanceof CraftingInventory) + { + + // This is ran one tick after the click because when the event is fired, the inventory + // object is not updated, and so the result of the isValidCompassResult is invalid. + + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + if (p.getRecipesManager().isValidCompassRecipe(((CraftingInventory) inventory).getMatrix())) + { + + // Puts the compass in the result slot + if (ev.getSlotType() == SlotType.CRAFTING) + { + ((CraftingInventory) inventory).setResult(new ItemStack(Material.COMPASS)); + ev.setResult(Result.ALLOW); + + ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed + } + + // Consumes the materials in the crafting grid. + // Because this is not an "official" recipe, we need to do that manually. + else if (ev.getSlotType() == SlotType.RESULT) + { + int index = 1; + for (ItemStack stack : ((CraftingInventory) inventory).getMatrix()) + { + if (stack == null) continue; + + if (stack.getAmount() != 1) + { + stack.setAmount(stack.getAmount() - 1); + inventory.setItem(index, stack); + } + else + { + inventory.setItem(index, new ItemStack(Material.AIR)); + } + + index++; + } + + ev.setCurrentItem(new ItemStack(Material.COMPASS)); + ev.setResult(Result.ALLOW); + + ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed + } + + return; + } + } + + }, 1L); + } + + + /** Prevent an apple to be renamed to/from the name of an head apple. **/ + + else if (inventory instanceof AnvilInventory) + { + InventoryView view = ev.getView(); + int rawSlot = ev.getRawSlot(); + + if (rawSlot == view.convertSlot(rawSlot)) + { // ensure we are talking about the upper inventory + if (rawSlot == 2) + { // "result" slot + ItemStack item = ev.getCurrentItem(); + if (item != null) + { // result slot non empty + ItemMeta meta = item.getItemMeta(); + + HashSet<String> prohibited = new HashSet<String>(); + + prohibited.add(ChatColor.RESET + I.t("{aqua}Golden head")); + prohibited.add(ChatColor.RESET + I.t("{lightpurple}Golden head")); + + // It is possible that the client filters the name of the golden apple in the anvil UI, + // removing all §. + for (String prohibition : new HashSet<>(prohibited)) + { + prohibited.add(prohibition.replace("§", "")); + } + + + // An item can't be renamed to the name of a golden head + if (meta != null && meta.hasDisplayName()) + { + if (prohibited.contains(meta.getDisplayName())) + { + ev.setCancelled(true); // nope nope nope + } + } + + // A golden head can't be renamed to any other name + if (view.getItem(0) != null) + { // slot 0 = first slot + ItemMeta metaOriginal = view.getItem(0).getItemMeta(); + + if (metaOriginal != null && metaOriginal.hasDisplayName()) + { + if (prohibited.contains(metaOriginal.getDisplayName())) + { + ev.setCancelled(true); + } + } + } + } + } + } + } + } + } + + + /** + * Used to craft the special compass (“semi-shapeless” recipe). + */ + @EventHandler (ignoreCancelled = true) + public void onInventoryDrag(final InventoryDragEvent ev) + { + if (ev.getInventory() instanceof CraftingInventory) + { + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + if (p.getRecipesManager().isValidCompassRecipe(((CraftingInventory) ev.getInventory()).getMatrix())) + { + ((CraftingInventory) ev.getInventory()).setResult(new ItemStack(Material.COMPASS)); + ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed + } + } + }, 1L); + } + } + + + /** + * Adds the team banner on crafted shields. + * + * Done indirectly because the plugin must be able to run + * on Minecraft 1.8. + */ + @EventHandler (ignoreCancelled = true) + public void onShieldPreCraft(PrepareItemCraftEvent ev) + { + if (!UHConfig.TEAMS_OPTIONS.BANNER.SHIELDS.ADD_ON_SHIELDS.get()) return; + + final Player player = (Player) ev.getViewers().get(0); + final UHTeam team = UHCReloaded.get().getTeamManager().getTeamForPlayer(player); + + if (team == null || team.getBanner() == null) return; + + final ItemStack result = ev.getRecipe().getResult(); + + final Material MATERIAL_SHIELD = Material.getMaterial("SHIELD"); + if (MATERIAL_SHIELD == null) return; // MC 1.8 + + if (result != null && result.getType() == MATERIAL_SHIELD) + { + try + { + final BannerMeta banner = (BannerMeta) team.getBanner().getItemMeta(); + + final BlockStateMeta bsMeta = (BlockStateMeta) result.getItemMeta(); + final Banner shieldBanner = (Banner) bsMeta.getBlockState(); + + shieldBanner.setBaseColor(banner.getBaseColor()); + shieldBanner.setPatterns(banner.getPatterns()); + + shieldBanner.update(); + + bsMeta.setBlockState(shieldBanner); + result.setItemMeta(bsMeta); + + ev.getInventory().setResult(result); + } + catch (ClassCastException | NullPointerException ignored) + { + // Bad Minecraft version (1.8) + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/FreezerListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/FreezerListener.java new file mode 100644 index 0000000..65c6125 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/FreezerListener.java @@ -0,0 +1,190 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.entity.ItemDespawnEvent; +import org.bukkit.event.player.PlayerMoveEvent; + + +public class FreezerListener implements Listener +{ + + private UHCReloaded p = null; + + public FreezerListener(UHCReloaded p) + { + this.p = p; + } + + + /** + * Used to prevent frozen players to break blocks. + * + * @param ev + */ + @EventHandler + public void onBlockBreakEvent(final BlockBreakEvent ev) + { + if (p.getFreezer().isPlayerFrozen(ev.getPlayer())) + { + ev.setCancelled(true); + } + } + + + /** + * Used to prevent frozen players to place blocks. + * + * @param ev + */ + @EventHandler + public void onBlockPlaceEvent(final BlockPlaceEvent ev) + { + if (p.getFreezer().isPlayerFrozen(ev.getPlayer())) + { + ev.setCancelled(true); + } + } + + + /** + * Used to freeze the players. + * + * @param ev + */ + @EventHandler + public void onPlayerMove(PlayerMoveEvent ev) + { + p.getFreezer().freezePlayerIfNeeded(ev.getPlayer(), ev.getFrom(), ev.getTo()); + } + + + /** + * Used to prevent the bows to be used while in global freeze mode. + * + * @param ev + */ + @EventHandler + public void onEntityShoot(EntityShootBowEvent ev) + { + if ((ev.getEntity() instanceof Player && p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) + || p.getFreezer().getGlobalFreezeState()) + { + + ev.setCancelled(true); + + // If a shoot from a player is cancelled, the arrow seems to be + // consumed in the player' screen. + // The inventory needs to be updated for the arrow to "come back". + if (ev.getEntity() instanceof Player) + { + ((Player) ev.getEntity()).updateInventory(); + } + } + } + + + /** + * Used to prevent items from despawning if the game is frozen. + * + * @param ev + */ + @EventHandler + public void onItemDespawn(ItemDespawnEvent ev) + { + if (p.getFreezer().getGlobalFreezeState()) + { + ev.setCancelled(true); + } + } + + + /** + * Used to freeze the mobs spawning while the game is frozen. + * @param ev + */ + @EventHandler + public void onEntitySpawn(CreatureSpawnEvent ev) + { + if (p.getFreezer().getGlobalFreezeState() && ev.getEntity() instanceof Creature) + { + p.getFreezer().freezeCreature((Creature) ev.getEntity(), true); + } + } + + + /** + * Used to disable any damages if the player is frozen. + * + * @param ev + */ + @EventHandler + public void onEntityDamage(final EntityDamageEvent ev) + { + if (ev.getEntity() instanceof Player) + { + if (p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) + { + ev.setCancelled(true); + } + } + } + + /** + * Used to cancel any food loss (but the players can still eat). + * + * @param ev + */ + @EventHandler + public void onFoodUpdate(FoodLevelChangeEvent ev) + { + if (p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) + { + if (ev.getFoodLevel() < ((Player) ev.getEntity()).getFoodLevel()) + { + ev.setCancelled(true); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java new file mode 100644 index 0000000..9c645ba --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java @@ -0,0 +1,829 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.events.EpisodeChangedCause; +import eu.carrade.amaury.UHCReloaded.events.TimerEndsEvent; +import eu.carrade.amaury.UHCReloaded.events.TimerStartsEvent; +import eu.carrade.amaury.UHCReloaded.events.UHEpisodeChangedEvent; +import eu.carrade.amaury.UHCReloaded.events.UHGameEndsEvent; +import eu.carrade.amaury.UHCReloaded.events.UHGameStartsEvent; +import eu.carrade.amaury.UHCReloaded.events.UHPlayerDeathEvent; +import eu.carrade.amaury.UHCReloaded.events.UHPlayerResurrectedEvent; +import eu.carrade.amaury.UHCReloaded.events.UHTeamDeathEvent; +import eu.carrade.amaury.UHCReloaded.misc.RuntimeCommandsExecutor; +import eu.carrade.amaury.UHCReloaded.protips.ProTips; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.utils.UHSound; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.runners.RunTask; +import fr.zcraft.zlib.tools.text.Titles; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.SkullType; +import org.bukkit.block.Banner; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerAchievementAwardedEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerLoginEvent.Result; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.PlayerStatisticIncrementEvent; +import org.bukkit.event.server.ServerListPingEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + + +public class GameListener implements Listener +{ + private final UHCReloaded p; + + private final Set<UUID> enableSpectatorModeOnRespawn = new HashSet<>(); + + + public GameListener(UHCReloaded p) + { + this.p = p; + } + + + /** + * Used to: + * - call events (UHPlayerDeathEvent, UHTeamDeathEvent, UHGameEndsEvent); + * - play the death sound; + * - update the scoreboard; + * - kick the player (if needed); + * - broadcast a team-death message (if needed); + * - highlight the death message in the console; + * - increase visibility of the death message (if needed); + * - drop the skull of the dead player (if needed); + * - send a ProTip to the killer about the "golden heads" (if needed); + * - update the number of alive players/teams; + * - save the location of the death of the player, to allow a teleportation later; + * - show the death location on the dynmap (if needed); + * - give XP to the killer (if needed); + * - notify the player about the possibility of respawn if hardcore hearts are enabled; + * - update the MOTD if needed; + * - disable the team-chat-lock if needed. + */ + @EventHandler + public void onPlayerDeath(final PlayerDeathEvent ev) + { + // This needs to be executed only if the player die as a player, not a spectator. + // Also, the game needs to be started. + if (p.getGameManager().isPlayerDead(ev.getEntity()) || !p.getGameManager().isGameStarted()) + { + return; + } + + p.getServer().getPluginManager().callEvent(new UHPlayerDeathEvent(ev.getEntity(), ev)); + + // Plays sound. + p.getGameManager().getDeathSound().broadcast(); + + // Send lightning strike if needed. + if (UHConfig.DEATH.ANNOUNCEMENTS.LIGHTNING_STRIKE.get()) + { + ev.getEntity().getLocation().getWorld().strikeLightningEffect(ev.getEntity().getLocation()); + } + + // Removes the player from the alive players. + this.p.getGameManager().addDead(ev.getEntity()); + + // Remember to enable spectator mode on respawn + enableSpectatorModeOnRespawn.add(ev.getEntity().getUniqueId()); + + // Kicks the player if needed. + if (UHConfig.DEATH.KICK.DO.get()) + { + Bukkit.getScheduler().runTaskLater(this.p, new Runnable() + { + + @Override + public void run() + { + /// The kick message of a player when death.kick.do = true in config + ev.getEntity().kickPlayer(I.t("jayjay")); + } + }, 20L * UHConfig.DEATH.KICK.TIME.get()); + } + + // Drops the skull of the player. + if (UHConfig.DEATH.HEAD.DROP.get()) + { + if (!UHConfig.DEATH.HEAD.PVP_ONLY.get() || (UHConfig.DEATH.HEAD.PVP_ONLY.get() && ev.getEntity().getKiller() != null)) + { + Location l = ev.getEntity().getLocation(); + ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (short) SkullType.PLAYER.ordinal()); + SkullMeta skullMeta = (SkullMeta) skull.getItemMeta(); + skullMeta.setOwner(ev.getEntity().getName()); + skullMeta.setDisplayName(ChatColor.RESET + ev.getEntity().getDisplayName()); + skull.setItemMeta(skullMeta); + l.getWorld().dropItem(l, skull); + + // Protip + if (ev.getEntity().getKiller() instanceof Player) + { + final Player killer = ev.getEntity().getKiller(); + RunTask.later(new Runnable() + { + @Override + public void run() + { + ProTips.CRAFT_GOLDEN_HEAD.sendTo(killer); + } + }, 200L); + } + } + } + + // Give XP to the killer (if needed) + if (UHConfig.DEATH.GIVE_XP_TO_KILLER.LEVELS.get() > 0) + { + Entity killer = ev.getEntity().getKiller(); + if (killer != null) + { + boolean inSameTeam = p.getTeamManager().inSameTeam(ev.getEntity(), (Player) killer); + boolean onlyOtherTeam = UHConfig.DEATH.GIVE_XP_TO_KILLER.ONLY_OTHER_TEAM.get(); + + if ((onlyOtherTeam && !inSameTeam) || !onlyOtherTeam) + { + ((Player) killer).giveExpLevels(UHConfig.DEATH.GIVE_XP_TO_KILLER.LEVELS.get()); + } + } + } + + // Sends a team-death message & event if needed. + final UHTeam team = p.getTeamManager().getTeamForPlayer(ev.getEntity()); + if (team != null) + { + boolean isAliveTeam = false; + + for (UUID playerID : team.getPlayersUUID()) + { + if (!p.getGameManager().isPlayerDead(playerID)) + { + isAliveTeam = true; + break; + } + } + + if (!isAliveTeam) + { + p.getServer().getPluginManager().callEvent(new UHTeamDeathEvent(team)); + + if (UHConfig.DEATH.MESSAGES.NOTIFY_IF_TEAM_HAS_FALLEN.get()) + { + // Used to display this message after the death message. + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + String format = ChatColor.translateAlternateColorCodes('&', UHConfig.DEATH.MESSAGES.TEAM_DEATH_MESSAGES_FORMAT.get()); + p.getServer().broadcastMessage(I.t("{0}The team {1} has fallen!", format, team.getDisplayName() + format)); + } + }, 1L); + } + } + } + + // Highlights the death message in the console + p.getServer().getConsoleSender().sendMessage(ChatColor.GOLD + "-- Death of " + ev.getEntity().getDisplayName() + ChatColor.GOLD + " (" + ev.getDeathMessage() + ") --"); + + // Customizes the death message + String dmFormat = ChatColor.translateAlternateColorCodes('&', UHConfig.DEATH.MESSAGES.DEATH_MESSAGES_FORMAT.get()); + String deathMessage = dmFormat + ev.getDeathMessage(); + deathMessage = deathMessage.replace(ev.getEntity().getName(), ev.getEntity().getDisplayName() + dmFormat); + if (ev.getEntity().getKiller() != null) + { + deathMessage = deathMessage.replace(ev.getEntity().getKiller().getName(), ev.getEntity().getKiller().getDisplayName() + dmFormat); + } + ev.setDeathMessage(deathMessage); + + // Saves the location of the death + p.getGameManager().addDeathLocation(ev.getEntity(), ev.getEntity().getLocation()); + + // Shows the death location on the dynmap + p.getDynmapIntegration().showDeathLocation(ev.getEntity()); + + // Is the game ended? If so, we need to call an event. + if (p.getGameManager().isGameRunning() && p.getGameManager().getAliveTeamsCount() == 1) + { + p.getGameManager().setGameFinished(true); + + // There's only one team alive, so the winner team is the first one. + p.getServer().getPluginManager().callEvent(new UHGameEndsEvent(p.getGameManager().getAliveTeams().iterator().next())); + } + + // Notifies the player about the possibility of respawn if hardcore hearts are enabled + if (UHConfig.HARDCORE_HEARTS.DISPLAY.get() && p.getProtocolLibIntegrationWrapper().isProtocolLibIntegrationEnabled() && UHConfig.HARDCORE_HEARTS.RESPAWN_MESSAGE.get()) + { + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + /// A message displayed to the players under the death screen, about the respawn possibility even if the death screen says the opposite (in hardcore mode) + ev.getEntity().sendMessage(I.t("{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next screen.")); + } + }, 2L); + } + + // Disables the team-chat-lock if needed + if (UHConfig.TEAMS_OPTIONS.TEAM_CHAT.DISABLE_LOCK_ON_DEATH.get()) + { + if (p.getTeamChatManager().isTeamChatEnabled(ev.getEntity())) + { + p.getTeamChatManager().toggleChatForPlayer(ev.getEntity()); + } + } + + // Updates the list headers & footers. + p.getPlayerListHeaderFooterManager().updateHeadersFooters(); + } + + + /** + * Used to enable the spectator mode when the player respawns. + */ + @EventHandler + public void onPlayerRespawn(final PlayerRespawnEvent ev) + { + if (enableSpectatorModeOnRespawn.remove(ev.getPlayer().getUniqueId())) + { + RunTask.nextTick(new Runnable() { + @Override + public void run() + { + p.getSpectatorsManager().setSpectating(ev.getPlayer(), true); + } + }); + } + } + + + /** + * Used to disable all damages if the game is not started. + * + * @param ev + */ + @EventHandler + public void onEntityDamage(final EntityDamageEvent ev) + { + if (ev.getEntity() instanceof Player) + { + if (!p.getGameManager().isTakingDamage() || (UHConfig.BEFORE_START.ENABLE_PVP.get() && !p.getGameManager().isGameRunning())) + { + ev.setCancelled(true); + } + } + } + + + /** + * Used to prevent the food level from dropping if the game has not started. + * + * @param ev + */ + @EventHandler + public void onFoodUpdate(final FoodLevelChangeEvent ev) + { + if (!p.getGameManager().isGameRunning()) + { + if (ev.getEntity() instanceof Player) + { + ((Player) ev.getEntity()).setFoodLevel(20); + ((Player) ev.getEntity()).setSaturation(20f); + } + + ev.setCancelled(true); + } + } + + + /** + * Used to display our custom state-based MOTD (if needed). + */ + @EventHandler + public void onServerListPing(final ServerListPingEvent ev) + { + if (p.getMOTDManager().isEnabled()) + { + ev.setMotd(p.getMOTDManager().getCurrentMOTD()); + } + } + + + /** + * Used to prevent the player to login after his death (if needed). + */ + @EventHandler + public void onPlayerLogin(final PlayerLoginEvent ev) + { + if (p.getGameManager().isGameStarted() + && p.getGameManager().isPlayerDead(ev.getPlayer()) + && !p.getGameManager().isDeadPlayersToBeResurrected(ev.getPlayer()) + && !p.getGameManager().getStartupSpectators().contains(ev.getPlayer().getName()) + && !UHConfig.DEATH.KICK.ALLOW_RECONNECT.get()) + { + + ev.setResult(Result.KICK_OTHER); + /// The kick message displayed if a player tries to relog after his death and it's forbidden by the config. + ev.setKickMessage(I.t("You are dead!")); + } + } + + + /** + * Used to: + * - change the gamemode of the player, if the game is not running; + * - teleport the player to the spawn, if the game is not running; + * - update the scoreboard; + * - put a new player in spectator mode if the game is started (following the config); + * - resurrect a player (if the player was offline). + */ + @EventHandler (priority = EventPriority.HIGHEST) + public void onPlayerJoin(final PlayerJoinEvent ev) + { + if (!this.p.getGameManager().isGameStarted()) + { + if (!p.getGameManager().isSlowStartInProgress()) + { + // Initialization of the player (teleportation, life, health objective score...). + p.getGameManager().initPlayer(ev.getPlayer()); + + // Teams selector. + if (UHConfig.TEAMS_OPTIONS.GUI.AUTO_DISPLAY.get() && p.getTeamManager().getTeams().size() != 0) + { + RunTask.later(new Runnable() + { + @Override + public void run() + { + if (p.getTeamManager().getTeamForPlayer(ev.getPlayer()) == null) + { + p.getTeamManager().displayTeamChooserChatGUI(ev.getPlayer()); + } + } + }, 20l * UHConfig.TEAMS_OPTIONS.GUI.DELAY.get()); + } + + // Rules + if (p.getRulesManager().displayOnJoin()) + { + RunTask.later(new Runnable() { + @Override + public void run() + { + p.getRulesManager().displayRulesTo(ev.getPlayer()); + } + }, 15 * 20l); + } + } + else + { + // Without that the player will be kicked for flying. + ev.getPlayer().setAllowFlight(true); + ev.getPlayer().setFlying(true); + } + } + + // Mainly useful on the first join. + p.getScoreboardManager().setScoreboardForPlayer(ev.getPlayer()); + + // The headers & footers needs to be (re)sent. + p.getPlayerListHeaderFooterManager().sendTo(ev.getPlayer()); + + // The display name is reset when the player logs off. + p.getTeamManager().colorizePlayer(ev.getPlayer()); + + if (!p.getGameManager().isGameStarted() && ev.getPlayer().hasPermission("uh.*")) + { + // A warning to the administrators if WorldBorder is not present. + if (!p.getWorldBorderIntegration().isWBIntegrationEnabled()) + { + ev.getPlayer().sendMessage(I.t("{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!")); + ev.getPlayer().sendMessage(I.t("{gray}Also, without WorldBorder, the border can't be reduced during the game (warnings excluded).")); + ev.getPlayer().sendMessage(I.t("{gray}Just install the plugin; UHPlugin will automatically configure it.")); + } + + // The same for ProtocolLib + if (!p.getProtocolLibIntegrationWrapper().isProtocolLibIntegrationEnabled()) + { + List<String> enabledOptionsWithProtocolLibNeeded = p.getProtocolLibIntegrationWrapper().isProtocolLibNeeded(); + + if (enabledOptionsWithProtocolLibNeeded != null) + { + ev.getPlayer().sendMessage(I.t("{darkred}[UHC] {ce}ProtocolLib is needed but not installed!")); + ev.getPlayer().sendMessage(I.t("{gray}The following options require the presence of ProtocolLib:")); + for (String option : enabledOptionsWithProtocolLibNeeded) + { + /// An option requiring ProtocolLib, in the “missing PLib” message. {0} = option path. + ev.getPlayer().sendMessage(I.tc("protocollib_option", "{darkgray} - {gray}{0}", option)); + } + + String pLibDownloadURL; + if (p.getServer().getBukkitVersion().contains("1.7")) // 1.7.9 or 1.7.10 + { + pLibDownloadURL = "http://dev.bukkit.org/bukkit-plugins/protocollib/"; + } + else // 1.8+ + { + pLibDownloadURL = "http://www.spigotmc.org/resources/protocollib.1997/"; + } + /// {0} = ProtocolLib download URL for the current Minecraft version. + ev.getPlayer().sendMessage(I.t("{gray}ProtocolLib is available here: {0}", pLibDownloadURL)); + } + } + } + + // If the player needs to be resurrected... + if (p.getGameManager().isDeadPlayersToBeResurrected(ev.getPlayer())) + { + p.getGameManager().resurrectPlayerOnlineTask(ev.getPlayer()); + p.getGameManager().markPlayerAsResurrected(ev.getPlayer()); + } + + // If the player is a new one, the game is started, and the option is set to true... + if (p.getGameManager().isGameRunning() && UHConfig.SPECTATOR_MODE_WHEN_NEW_PLAYER_JOIN_AFTER_START.get() + && !p.getGameManager().getAlivePlayers().contains(ev.getPlayer())) + { + p.getSpectatorsManager().setSpectating(ev.getPlayer(), true); + } + } + + /** + * Used to disable the achievements before the game. + */ + @EventHandler + public void onPlayerAchievementAwarded(final PlayerAchievementAwardedEvent ev) + { + if (!p.getGameManager().isGameStarted() && UHConfig.ACHIEVEMENTS.DISABLE_ACHIEVEMENTS_BEFORE_START.get()) + { + ev.setCancelled(true); + } + } + + /** + * Used to disable the statistics before the game. + */ + @EventHandler + public void onPlayerStatisticIncrement(final PlayerStatisticIncrementEvent ev) + { + if (!p.getGameManager().isGameStarted() && UHConfig.STATISTICS.DISABLE_STATISTICS_BEFORE_START.get()) + { + ev.setCancelled(true); + } + } + + + /** + * Used to prevent players from breaking blocks if the game is not currently running. + */ + @EventHandler + public void onBlockBreakEvent(final BlockBreakEvent ev) + { + if (!this.p.getGameManager().isGameStarted() && !ev.getPlayer().hasPermission("uh.build")) + { + ev.setCancelled(true); + } + } + + /** + * Used to prevent players from placing blocks if the game is not currently running. + */ + @EventHandler + public void onBlockPlaceEvent(final BlockPlaceEvent ev) + { + if (!this.p.getGameManager().isGameStarted() && !ev.getPlayer().hasPermission("uh.build")) + { + ev.setCancelled(true); + } + } + + + /** + * Used to send the chat to the team-chat if this team-chat is enabled. + */ + // Priority LOWEST to be able to cancel the event before all other plugins + @EventHandler (priority = EventPriority.LOWEST) + public void onAsyncPlayerChat(final AsyncPlayerChatEvent ev) + { + // If the event is asynchronous, the message was sent by a "real" player. + // Else, the message was sent by a plugin (like our /g command, or another plugin), and + // the event is ignored. + if (ev.isAsynchronous()) + { + if (p.getTeamChatManager().isTeamChatEnabled(ev.getPlayer())) + { + ev.setCancelled(true); + p.getTeamChatManager().sendTeamMessage(ev.getPlayer(), ev.getMessage()); + } + else if (p.getTeamChatManager().isOtherTeamChatEnabled(ev.getPlayer())) + { + ev.setCancelled(true); + p.getTeamChatManager().sendTeamMessage(ev.getPlayer(), ev.getMessage(), p.getTeamChatManager().getOtherTeamEnabled(ev.getPlayer())); + } + } + } + + /** + * Used to: + * - update the internal list of running timers; + * - shift the episode if the main timer is up (and restart this main timer); + * - hide an other timer when it is up. + */ + @EventHandler + public void onTimerEnds(final TimerEndsEvent ev) + { + p.getTimerManager().updateStartedTimersList(); + + if (ev.getTimer().equals(p.getTimerManager().getMainTimer())) + { + // If this timer is the main one, we shifts an episode. + p.getGameManager().shiftEpisode(); + ev.setRestart(true); + } + else + { + ev.getTimer().setDisplayed(false); + } + + if (ev.getTimer().equals(p.getBorderManager().getWarningTimer()) && ev.wasTimerUp()) + { + p.getBorderManager().getWarningSender().sendMessage(I.t("{cs}The timer before the new border is up!")); + p.getBorderManager().sendCheckMessage(p.getBorderManager().getWarningSender(), p.getBorderManager().getWarningSize()); + } + } + + /** + * Used to: + * - update the internal list of running timers; + * - display a timer when it is started. + */ + @EventHandler + public void onTimerStarts(final TimerStartsEvent ev) + { + p.getTimerManager().updateStartedTimersList(); + + if (!ev.getTimer().equals(p.getTimerManager().getMainTimer())) + { + ev.getTimer().setDisplayed(true); + } + } + + + /** + * Used to broadcast the episode change. + */ + @EventHandler + public void onEpisodeChange(final UHEpisodeChangedEvent ev) + { + String message; + + if (ev.getCause() == EpisodeChangedCause.SHIFTED) + { + message = I.t("{aqua}-------- End of episode {0} [forced by {1}] --------", String.valueOf(ev.getNewEpisode() - 1), ev.getShifter()); + } + else + { + message = I.t("{aqua}-------- End of episode {0} --------", String.valueOf(ev.getNewEpisode() - 1)); + } + + p.getServer().broadcastMessage(message); + + + // Broadcasts title + if (UHConfig.EPISODES.TITLE.get()) + { + Titles.broadcastTitle( + 5, 32, 8, + /// The title displayed when the episode change. {0} = new episode number; {1} = old. + I.t("{darkaqua}Episode {aqua}{0}", ev.getNewEpisode(), ev.getNewEpisode() - 1), + "" + ); + } + + + // Updates the list headers & footers. + p.getPlayerListHeaderFooterManager().updateHeadersFooters(); + } + + + /** + * Used to: + * - broadcast the beginning of a game, with sound & message; + * - schedule the commands executed after the beginning of the game. + */ + @EventHandler + public void onGameStarts(final UHGameStartsEvent ev) + { + // Start sound + new UHSound(UHConfig.START.SOUND).broadcast(); + + // Broadcast + /// Start message broadcasted in chat + Bukkit.getServer().broadcastMessage(I.t("{green}--- GO ---")); + + // Title + if (UHConfig.START.DISPLAY_TITLE.get()) + { + Titles.broadcastTitle( + 5, 40, 8, + /// Title of title displayed when the game starts. + I.t("{darkgreen}Let's go!"), + /// Subtitle of title displayed when the game starts. + I.t("{green}Good luck, and have fun") + ); + } + + // Commands + p.getRuntimeCommandsExecutor().registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_GAME_START); + + // Border shrinking + p.getBorderManager().scheduleBorderReduction(); + + // MOTD + p.getMOTDManager().updateMOTDDuringGame(); + + // List headers & footers. + p.getPlayerListHeaderFooterManager().updateHeadersFooters(); + + // Rules + if (p.getRulesManager().displayOnStart()) + { + RunTask.later(new Runnable() { + @Override + public void run() + { + p.getRulesManager().broadcastRules(); + } + }, 15 * 20l); + } + + // Banners + if (p.getGameManager().START_GIVE_BANNER || p.getGameManager().START_PLACE_BANNER_HEAD || p.getGameManager().START_PLACE_BANNER_SPAWN) + { + RunTask.later(new Runnable() { + @Override + public void run() + { + for (UHTeam team : p.getTeamManager().getTeams()) + { + if (!team.isEmpty()) + { + ItemStack banner = team.getBanner(); + for (Player player : team.getOnlinePlayers()) + { + if (p.getGameManager().START_GIVE_BANNER) + player.getInventory().setItem(8, banner); + + if (p.getGameManager().START_PLACE_BANNER_HEAD) + player.getInventory().setHelmet(banner); + + if (p.getGameManager().START_PLACE_BANNER_SPAWN) + { + Block place = player.getWorld().getHighestBlockAt(player.getLocation()); + Block under = place.getRelative(BlockFace.DOWN); + + // We don't want a stack of banners + if (under.getType() != Material.STANDING_BANNER) + { + if (!under.getType().isSolid()) + under.setType(Material.WOOD); + + place.setType(Material.STANDING_BANNER); + + Banner bannerBlock = (Banner) place.getState(); + BannerMeta bannerMeta = (BannerMeta) banner.getItemMeta(); + + bannerBlock.setBaseColor(bannerMeta.getBaseColor()); + bannerBlock.setPatterns(bannerMeta.getPatterns()); + + bannerBlock.update(); + } + } + } + } + } + } + }, 5l); + } + } + + /** + * Used to: + * - broadcast the winner(s) and launch some fireworks if needed, a few seconds later; + * - schedule the commands executed after the end of the game. + */ + @EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onGameEnd(final UHGameEndsEvent ev) + { + if (UHConfig.FINISH.AUTO.DO.get()) + { + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + try + { + p.getGameManager().finishGame(); + } + catch (IllegalStateException e) + { + // The game is not finished (..what?). + e.printStackTrace(); + } + } + }, UHConfig.FINISH.AUTO.TIME_AFTER_LAST_DEATH.get() * 20L); + } + + // Commands + p.getRuntimeCommandsExecutor().registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_GAME_END); + + // Updates the MOTD. + p.getMOTDManager().updateMOTDAfterGame(ev.getWinnerTeam()); + } + + + /** + * Used to: + * - disable the spectator mode; + * - hide the death point from the dynmap; + * - broadcast this resurrection to all players; + * - update the MOTD. + */ + @EventHandler + public void onPlayerResurrected(final UHPlayerResurrectedEvent ev) + { + // Spectator mode disabled + p.getSpectatorsManager().setSpectating(ev.getPlayer(), false); + + // Death point removed on the dynmap + p.getDynmapIntegration().hideDeathLocation(ev.getPlayer()); + + // All players are notified + /// Resurrection notification. {0} = raw resurrected player name. + p.getServer().broadcastMessage(I.t("{gold}{0} returned from the dead!", ev.getPlayer().getName())); + + // Updates the MOTD. + p.getMOTDManager().updateMOTDDuringGame(); + + // Updates the list headers & footers. + p.getPlayerListHeaderFooterManager().updateHeadersFooters(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java new file mode 100644 index 0000000..b2f5346 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java @@ -0,0 +1,363 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.task.CancelBrewTask; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.inventory.BrewerInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.List; + + +public class GameplayListener implements Listener +{ + + private UHCReloaded p = null; + + public GameplayListener(UHCReloaded p) + { + this.p = p; + } + + + /** + * Used to replace ghast tears with gold (if needed). + */ + @EventHandler (ignoreCancelled = true) + public void onEntityDeath(EntityDeathEvent ev) + { + if (ev.getEntity() instanceof Ghast && UHConfig.GAMEPLAY_CHANGES.REPLACE_GHAST_TEARS_WITH_GOLD.get()) + { + List<ItemStack> drops = new ArrayList<ItemStack>(ev.getDrops()); + ev.getDrops().clear(); + for (ItemStack i : drops) + { + if (i.getType() == Material.GHAST_TEAR) + { + ev.getDrops().add(new ItemStack(Material.GOLD_INGOT, i.getAmount())); + } + else + { + ev.getDrops().add(i); + } + } + } + } + + /** + * Used to prevent the user to get a ghast tear, if forbidden by the config. + */ + @EventHandler (ignoreCancelled = true) + public void onPlayerPickupItem(PlayerPickupItemEvent ev) + { + if (ev.getItem().getItemStack().getType() == Material.GHAST_TEAR && ev.getPlayer().getGameMode().equals(GameMode.SURVIVAL) && UHConfig.GAMEPLAY_CHANGES.REPLACE_GHAST_TEARS_WITH_GOLD.get()) + { + ev.setCancelled(true); + } + } + + + /** + * Used to disable power-II potions. + */ + @EventHandler + public void onInventoryDrag(InventoryDragEvent ev) + { + if (UHConfig.GAMEPLAY_CHANGES.DISABLE_LEVEL_II_POTIONS.get() && ev.getInventory() instanceof BrewerInventory) + { + new CancelBrewTask((BrewerInventory) ev.getInventory(), ev.getWhoClicked()).runTaskLater(p, 1l); + } + } + + /** + * Used to disable power-II potions. + */ + @EventHandler + public void onInventoryClick(InventoryClickEvent ev) + { + if (UHConfig.GAMEPLAY_CHANGES.DISABLE_LEVEL_II_POTIONS.get() && ev.getInventory() instanceof BrewerInventory) + { + new CancelBrewTask((BrewerInventory) ev.getInventory(), ev.getWhoClicked()).runTaskLater(p, 1l); + } + } + + + /** + * Used to disable enderpearl damages (if needed). + */ + @EventHandler (ignoreCancelled = true) + public void onPlayerTeleport(final PlayerTeleportEvent ev) + { + if (UHConfig.GAMEPLAY_CHANGES.DISABLE_ENDERPEARLS_DAMAGES.get()) + { + if (ev.getCause() == TeleportCause.ENDER_PEARL) + { + ev.setCancelled(true); + ev.getPlayer().teleport(ev.getTo(), TeleportCause.PLUGIN); + } + } + } + + + /** + * Used to disable witch spawn (if needed). + */ + @EventHandler + public void onCreatureSpawn(CreatureSpawnEvent ev) + { + if (ev.getEntityType().equals(EntityType.WITCH)) + { + if (UHConfig.GAMEPLAY_CHANGES.WITCH.DISABLE_NATURAL_SPAWN.get() && ev.getSpawnReason().equals(SpawnReason.NATURAL)) + { + ev.setCancelled(true); + } + if (UHConfig.GAMEPLAY_CHANGES.WITCH.DISABLE_LIGHTNING_SPAWN.get() && ev.getSpawnReason().equals(SpawnReason.LIGHTNING)) + { + ev.setCancelled(true); + } + } + } + + + /** + * Used to change the amount of regenerated hearts from a golden apple. + */ + @EventHandler + public void onPlayerItemConsume(final PlayerItemConsumeEvent ev) + { + final int TICKS_BETWEEN_EACH_REGENERATION = 50; + final int DEFAULT_NUMBER_OF_HEARTS_REGEN = 4; + final int DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH = 180; + final int REGENERATION_LEVEL_GOLDEN_APPLE = 2; + final int REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE = 5; + + if (ev.getItem().getType() == Material.GOLDEN_APPLE) + { + ItemMeta meta = ev.getItem().getItemMeta(); + short dataValue = ev.getItem().getDurability(); + int halfHearts; + int level; + + if (meta.hasDisplayName() + && (meta.getDisplayName().equals(ChatColor.RESET + I.t("{aqua}Golden head")) + || meta.getDisplayName().equals(ChatColor.RESET + I.t("{lightpurple}Golden head")))) + { + if (dataValue == 0) + { // Normal golden apple from a head + halfHearts = UHConfig.GAMEPLAY_CHANGES.GOLDEN_APPLE.REGENERATION.FROM_NORMAL_HEAD.get(); + level = REGENERATION_LEVEL_GOLDEN_APPLE; + } + else + { // Notch golden apple from a head + halfHearts = UHConfig.GAMEPLAY_CHANGES.GOLDEN_APPLE.REGENERATION.FROM_NOTCH_HEAD.get(); + level = REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE; + } + } + else if (dataValue == 0) + { // Normal golden apple from an apple + halfHearts = UHConfig.GAMEPLAY_CHANGES.GOLDEN_APPLE.REGENERATION.NORMAL.get(); + level = REGENERATION_LEVEL_GOLDEN_APPLE; + } + else + { // Notch golden apple from an apple + halfHearts = UHConfig.GAMEPLAY_CHANGES.GOLDEN_APPLE.REGENERATION.NOTCH.get(); + level = REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE; + } + + // Technically, a level-I effect is « level 0 ». + final int realLevel = level - 1; + + + // What is needed to do? + if ((dataValue == 0 && halfHearts == DEFAULT_NUMBER_OF_HEARTS_REGEN) + || (dataValue == 1 && halfHearts == DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH)) + { + // Default behavior, nothing to do. + } + else if ((dataValue == 0 && halfHearts > DEFAULT_NUMBER_OF_HEARTS_REGEN) + || (dataValue == 1 && halfHearts > DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH)) + { + // If the heal needs to be increased, the effect can be applied immediately. + + int duration = ((int) Math.floor(TICKS_BETWEEN_EACH_REGENERATION / (Math.pow(2, realLevel)))) * halfHearts; + + new PotionEffect(PotionEffectType.REGENERATION, duration, realLevel).apply(ev.getPlayer()); + } + else + { + // The heal needs to be decreased. + // We can't apply the effect immediately, because the server will just ignore it. + // So, we apply it two ticks later, with one half-heart less (because in two ticks, + // one half-heart is given to the player). + final int healthApplied = halfHearts - 1; + + Bukkit.getScheduler().runTaskLater(this.p, new Runnable() + { + @Override + public void run() + { + // The original, vanilla, effect is removed + ev.getPlayer().removePotionEffect(PotionEffectType.REGENERATION); + + int duration = ((int) Math.floor(TICKS_BETWEEN_EACH_REGENERATION / (Math.pow(2, realLevel)))) * healthApplied; + + new PotionEffect(PotionEffectType.REGENERATION, duration, realLevel).apply(ev.getPlayer()); + } + }, 2l); + } + } + } + + + /** + * Used to update the compass. + */ + @SuppressWarnings ("deprecation") + @EventHandler + public void onPlayerInteract(PlayerInteractEvent ev) + { + if ((ev.getAction() == Action.RIGHT_CLICK_AIR || ev.getAction() == Action.RIGHT_CLICK_BLOCK) && ev.getPlayer().getItemInHand().getType() == Material.COMPASS && p.getConfig().getBoolean("gameplay-changes.compass.enabled") && !p.getGameManager().isPlayerDead(ev.getPlayer())) + { + Player player1 = ev.getPlayer(); + + Boolean foundRottenFlesh = false; + for (ItemStack item : player1.getInventory().getContents()) + { + if (item != null && item.getType() == Material.ROTTEN_FLESH) + { + if (item.getAmount() != 1) + { + item.setAmount(item.getAmount() - 1); + } + else + { + player1.getInventory().removeItem(item); + } + + player1.updateInventory(); + foundRottenFlesh = true; + break; + } + } + + if (!foundRottenFlesh) + { + /// Error message if a player tries to use his pointing compass without rotten flesh. + player1.sendMessage(I.t("{gray}{italic}You do not have rotten flesh.")); + player1.playSound(player1.getLocation(), Sound.STEP_WOOD, 1F, 1F); + return; + } + + Player nearest = null; + Double distance = 99999D; + for (Player player2 : p.getGameManager().getOnlineAlivePlayers()) + { + try + { + Double calc = player1.getLocation().distance(player2.getLocation()); + + if (calc > 1 && calc < distance) + { + distance = calc; + if (!player2.getUniqueId().equals(player1.getUniqueId()) && !p.getTeamManager().inSameTeam(player1, player2)) + { + nearest = player2.getPlayer(); + } + } + } + catch (Exception ignored) + { + + } + } + + if (nearest == null) + { + /// Error message if a player tries to use his pointing compass without a player nearby. + player1.sendMessage(I.t("{gray}{italic}Only silence answers your request.")); + + player1.playSound(player1.getLocation(), Sound.STEP_WOOD, 1F, 1F); + return; + } + + /// Success message when a player uses his pointing compass. + player1.sendMessage(I.t("{gray}The compass now points to the closest player.")); + player1.setCompassTarget(nearest.getLocation()); + + player1.playSound(player1.getLocation(), Sound.ENDERMAN_TELEPORT, 1F, 1F); + } + } + + + /** + * Used to disable the "bad" weather (aka non-clear weather). + * The weather is initially clear. + */ + @EventHandler + public void onWeatherChange(WeatherChangeEvent ev) + { + if (!UHConfig.GAMEPLAY_CHANGES.WEATHER.get()) + { + ev.setCancelled(true); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/PacketsListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/PacketsListener.java new file mode 100644 index 0000000..858bc00 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/PacketsListener.java @@ -0,0 +1,110 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.listeners; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.ListenerPriority; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.EnumWrappers; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; + +import java.lang.reflect.InvocationTargetException; + + +public class PacketsListener extends PacketAdapter implements Listener +{ + private UHCReloaded p = null; + private ProtocolManager pm = ProtocolLibrary.getProtocolManager(); + + private final PacketContainer respawnPacket; + + public PacketsListener(UHCReloaded p) + { + // This listener needs to listen on login packets only. + super(p, ListenerPriority.NORMAL, PacketType.Play.Server.LOGIN); + + this.p = p; + + // The packet to send to automatically respawn the player. + respawnPacket = pm.createPacket(PacketType.Play.Client.CLIENT_COMMAND); + respawnPacket.getClientCommands().write(0, EnumWrappers.ClientCommand.PERFORM_RESPAWN); + } + + /** + * Used to present the server as an hardcore server, for the clients to display hardcore hearts. + */ + @Override + public void onPacketSending(PacketEvent ev) + { + // If its a login packet, write the hardcore flag (first boolean) to true. + if (ev.getPacketType().equals(PacketType.Play.Server.LOGIN)) + { + ev.getPacket().getBooleans().write(0, true); + } + } + + /** + * Used to automatically respawn the dead players. + */ + @EventHandler + public void onPlayerDeath(final PlayerDeathEvent ev) + { + if (UHConfig.AUTO_RESPAWN.DO.get()) + { + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + try + { + pm.recieveClientPacket(ev.getEntity(), respawnPacket); + } + catch (IllegalAccessException | InvocationTargetException e) + { + e.printStackTrace(); + } + } + }, UHConfig.AUTO_RESPAWN.DELAY.get() * 20L); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/SpawnsListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/SpawnsListener.java new file mode 100644 index 0000000..31dcc05 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/listeners/SpawnsListener.java @@ -0,0 +1,231 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.listeners; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Ghast; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Rabbit; +import org.bukkit.entity.Slime; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.CreatureSpawnEvent; + +import java.util.Random; + + +public class SpawnsListener implements Listener +{ + private final Random random = new Random(); + + private final boolean RABBIT_SPAWN_ENABLED; + private final double RABBIT_SPAWN_PROBABILITY; + private final String RABBIT_NAME; + + public SpawnsListener() + { + RABBIT_SPAWN_ENABLED = UHConfig.GAMEPLAY_CHANGES.RABBIT.KILLER_RABBIT_SPAWN.get(); + RABBIT_SPAWN_PROBABILITY = UHConfig.GAMEPLAY_CHANGES.RABBIT.KILLER_RABBIT_SPAWN_PROBABILITY.get(); + + RABBIT_NAME = UHConfig.GAMEPLAY_CHANGES.RABBIT.KILLER_RABBIT_NAME.get().trim(); + } + + @EventHandler (priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onRabbitSpawn(CreatureSpawnEvent ev) + { + if (!RABBIT_SPAWN_ENABLED) + return; + + if (ev.getEntity().getType() != EntityType.RABBIT) + return; + + if (random.nextDouble() >= RABBIT_SPAWN_PROBABILITY) + return; + + Rabbit rabbit = (Rabbit) ev.getEntity(); + rabbit.setRabbitType(Rabbit.Type.THE_KILLER_BUNNY); + + if (!RABBIT_NAME.isEmpty()) + { + rabbit.setCustomName(RABBIT_NAME); + rabbit.setCustomNameVisible(true); + } + } + + + /** + * Used to cancel the spawn of the creatures if the game is not started. + * <p> + * We don't use the peaceful difficulty for that because it causes bugs with Minecraft 1.8 + * (the difficulty is not correctly updated client-side when the game starts). + */ + @EventHandler + public void onCreatureSpawn(CreatureSpawnEvent ev) + { + if (!UHCReloaded.get().getGameManager().isGameStarted() + && isNaturalSpawn(ev.getSpawnReason()) + && isHostile(ev.getEntityType())) + { + ev.setCancelled(true); + } + } + + /** + * Used to cancel the spawn of hostile entities on the surface only, at the beginning of the game. + */ + @EventHandler + public void onSurfaceCreatureSpawn(CreatureSpawnEvent ev) + { + if (UHCReloaded.get().getGameManager().isGameStarted() + && !UHCReloaded.get().getGameManager().isSurfaceSpawnEnabled() + && isNaturalSpawn(ev.getSpawnReason()) + && isHostile(ev.getEntityType())) + { + // We check the blocs above the entity to see if we only find surface blocks. + final Location spawnLocation = ev.getLocation(); + final World world = spawnLocation.getWorld(); + final int highestBlockY = world.getHighestBlockYAt(spawnLocation); + + final int x = spawnLocation.getBlockX(); + final int z = spawnLocation.getBlockZ(); + + boolean surface = true; + + for (int y = spawnLocation.getBlockY(); y <= highestBlockY; y++) + { + switch (world.getBlockAt(x, y, z).getType()) + { + // Air + case AIR: + + // Trees + case LOG: + case LOG_2: + case LEAVES: + case LEAVES_2: + case HUGE_MUSHROOM_1: + case HUGE_MUSHROOM_2: + + // Vegetation + case DEAD_BUSH: + case CROPS: + case GRASS: + case LONG_GRASS: + case DOUBLE_PLANT: + case YELLOW_FLOWER: + case VINE: + case SUGAR_CANE_BLOCK: + case BROWN_MUSHROOM: + case RED_MUSHROOM: + + // Nature + case SNOW: + + // Igloos + case SNOW_BLOCK: + + // Villages + case WOOD: + case WOOD_STAIRS: + case SANDSTONE_STAIRS: + case BOOKSHELF: + + // Redstone + case REDSTONE_WIRE: + case REDSTONE_COMPARATOR: + case REDSTONE_COMPARATOR_OFF: + case REDSTONE_COMPARATOR_ON: + case REDSTONE_TORCH_OFF: + case REDSTONE_TORCH_ON: + + // Other blocs frequently used on surface on custom maps + case TORCH: + case RAILS: + case ACTIVATOR_RAIL: + case DETECTOR_RAIL: + case POWERED_RAIL: + break; + + default: + surface = false; + } + + if (!surface) break; + } + + if (surface) ev.setCancelled(true); + } + } + + + /** + * Checks if a spawn is natural. + * + * @param reason The spawn reason. + * @return {@code true} if it's a natural spawn (not from a player or an interaction + * with another entity, as example). + */ + private boolean isNaturalSpawn(CreatureSpawnEvent.SpawnReason reason) + { + switch (reason) + { + case NATURAL: + case NETHER_PORTAL: + case LIGHTNING: + case SPAWNER: + return true; + + default: + return false; + } + } + + /** + * Checks if the given mod is hostile. + * @param entity The entity. + * @return {@code true} if hostile. + */ + private boolean isHostile(EntityType entity) + { + Class<? extends Entity> entityClass = entity.getEntityClass(); + + return Monster.class.isAssignableFrom(entityClass) + || Slime.class.isAssignableFrom(entityClass) + || Ghast.class.isAssignableFrom(entityClass); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/Freezer.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/Freezer.java new file mode 100644 index 0000000..4c7c502 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/Freezer.java @@ -0,0 +1,305 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.misc; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.listeners.FreezerListener; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.UUID; + + +public class Freezer +{ + private UHCReloaded p = null; + + private boolean isListenerRegistered = false; + private FreezerListener freezerListener = null; + + private Boolean globalFreeze = false; + private ArrayList<UUID> frozenPlayers = new ArrayList<>(); + private HashMap<UUID, Boolean> oldAllowFly = new HashMap<>(); + private HashMap<UUID, Boolean> oldFlyMode = new HashMap<>(); + + private boolean hiddenFreeze = false; + + + public Freezer(UHCReloaded plugin) + { + this.p = plugin; + + this.freezerListener = new FreezerListener(p); + } + + + /** + * Freezes a player, if needed. + * The player is blocked inside the block he is currently. + * + * This method is intended to be executed when a player moves. + * + * @param player The player to freeze + * @param from The old position from the PlayerMoveEvent + * @param to The new position from the PlayerMoveEvent + */ + public void freezePlayerIfNeeded(Player player, Location from, Location to) + { + if (frozenPlayers.contains(player.getUniqueId())) + { + // If the X, Y or Z coordinate of the player change, he needs to be teleported inside the old block. + // The yaw and pitch are conserved, to teleport more smoothly. + if (from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ()) + { + player.teleport(new Location(from.getWorld(), from.getBlockX() + 0.5, from.getBlockY(), from.getBlockZ() + 0.5, to.getYaw(), to.getPitch()), TeleportCause.PLUGIN); + } + } + } + + + /** + * Enables or disables the global freeze of players, mobs, timer. + * + * @param frozen If true the global freeze will be enabled. + * @param showStateInScoreboard If false, the freeze state will not be displayed in the scoreboard. + */ + public void setGlobalFreezeState(Boolean frozen, Boolean showStateInScoreboard) + { + this.globalFreeze = frozen; + this.hiddenFreeze = !showStateInScoreboard; + + if (frozen) + { + for (Player player : p.getGameManager().getOnlineAlivePlayers()) + { + this.setPlayerFreezeState(player, true); + } + + // Freezes the mobs by applying a Slowness effect. There isn't any EntityMoveEvent, so... + for (World world : p.getServer().getWorlds()) + { + for (Entity entity : world.getLivingEntities()) + { + if (entity instanceof Creature) + { + freezeCreature((Creature) entity, true); + } + } + } + + // Freezes the timers. + p.getTimerManager().pauseAllRunning(true); + } + + else + { + // All the online players are listed, not the internal list of frozen players, + // to avoid a ConcurrentModificationException if the iterated list is being emptied. + for (Player player : p.getServer().getOnlinePlayers()) + { + if (this.isPlayerFrozen(player)) + { + this.setPlayerFreezeState(player, false); + } + } + + // Removes the slowness effect + for (World world : p.getServer().getWorlds()) + { + for (Entity entity : world.getLivingEntities()) + { + if (entity instanceof Creature) + { + freezeCreature((Creature) entity, false); + } + } + } + + // Unfreezes the timers. + p.getTimerManager().pauseAllRunning(false); + } + + updateListenerRegistration(); + } + + /** + * Enables or disables the global freeze of players, mobs, timer. + * + * @param frozen If true the global freeze will be enabled. + */ + public void setGlobalFreezeState(Boolean frozen) + { + setGlobalFreezeState(frozen, true); + } + + + /** + * Returns the current state of the global freeze. + * + * @return True if the global freeze is enabled. + */ + public boolean getGlobalFreezeState() + { + return this.globalFreeze; + } + + /** + * Freezes a player. + * + * @param player The player to freeze. + * @param frozen If true the player will be frozen. If false, unfrozen. + */ + public void setPlayerFreezeState(Player player, Boolean frozen) + { + if (frozen && !this.frozenPlayers.contains(player.getUniqueId())) + { + this.frozenPlayers.add(player.getUniqueId()); + this.oldAllowFly.put(player.getUniqueId(), player.getAllowFlight()); + this.oldFlyMode.put(player.getUniqueId(), player.isFlying()); + + // Used to prevent the player to be kicked for fly if he was frozen during a fall. + // He is blocked inside his current block anyway. + player.setAllowFlight(true); + } + + if (!frozen && this.frozenPlayers.contains(player.getUniqueId())) + { + this.frozenPlayers.remove(player.getUniqueId()); + + player.setFlying(this.oldFlyMode.get(player.getUniqueId())); + player.setAllowFlight(this.oldAllowFly.get(player.getUniqueId())); + + this.oldAllowFly.remove(player.getUniqueId()); + this.oldFlyMode.remove(player.getUniqueId()); + } + + updateListenerRegistration(); + } + + /** + * Returns true if the given player is frozen. + * + * @param player The player to be checked. + * @return true if the given player is frozen. + */ + public boolean isPlayerFrozen(Player player) + { + return frozenPlayers.contains(player.getUniqueId()); + } + + /** + * Returns {@code true} if the current freeze must be hidden in the sidebar. + * + * @return {@code true} to hide it. + */ + public boolean isHiddenFreeze() + { + return hiddenFreeze; + } + + /** + * (Un)freezes a creature. + * + * @param creature The creature to freeze. + * @param frozen If true the creature will be frozen. Else... + */ + public void freezeCreature(Creature creature, Boolean frozen) + { + if (frozen) + { + // Freezes the creature for about 68 years. + creature.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, Integer.MAX_VALUE, 100, true)); + } + else + { + creature.removePotionEffect(PotionEffectType.SLOW); + } + } + + /** + * Registers the listener if it wasn't registered, and unregisters this listener + * if there isn't any frozen player. + * + * Call this AFTER registering the first frozen player, and AFTER unregistering + * the last one. + */ + private void updateListenerRegistration() + { + // Registers the listener if needed + // (i.e if there isn't any frozen player, or if the global freeze is enabled). + if (!this.isListenerRegistered) + { + if (!this.frozenPlayers.isEmpty() || this.getGlobalFreezeState()) + { + p.getServer().getPluginManager().registerEvents(freezerListener, p); + this.isListenerRegistered = true; + } + } + + // Unregisters the listener if needed + else + { + if (this.frozenPlayers.isEmpty() && !this.getGlobalFreezeState()) + { + HandlerList.unregisterAll(freezerListener); + this.isListenerRegistered = false; + } + } + } + + + /** + * Returns the list of the currently frozen players. + * + * @return The list. + */ + public ArrayList<Player> getFrozenPlayers() + { + ArrayList<Player> frozenPlayersList = new ArrayList<>(); + + for (UUID id : frozenPlayers) + { + frozenPlayersList.add(p.getServer().getPlayer(id)); + } + + return frozenPlayersList; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java new file mode 100644 index 0000000..21ec7a7 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java @@ -0,0 +1,145 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.misc; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.ChatColor; + + +public class MOTDManager +{ + private UHCReloaded p; + + private boolean enabled; + private String matchName = ""; + + private String currentMOTD; + + public MOTDManager(UHCReloaded plugin) + { + p = plugin; + + enabled = UHConfig.MOTD.ENABLED.get(); + + if (enabled && UHConfig.MOTD.DISPLAY_MATCH_NAME.get()) + { + matchName = ChatColor.translateAlternateColorCodes('&', UHConfig.MOTD.MATCH_NAME_PREFIX.get()) + p.getScoreboardManager().getScoreboardName() + ChatColor.RESET + "\n"; + } + } + + /** + * Returns the current MOTD. + * + * @return The MOTD. + */ + public String getCurrentMOTD() + { + return currentMOTD; + } + + /** + * Returns true if the state-based MOTDs are enabled. + * + * @return true if enabled. + */ + public boolean isEnabled() + { + return enabled; + } + + + /** + * Updates the MOTD to the one displayed before the game start. + */ + public void updateMOTDBeforeStart() + { + /// MOTD when the game is not started. + if (enabled) currentMOTD = matchName + I.t("Waiting for players..."); + } + + /** + * Updates the MOTD to the one displayed during the start. + */ + public void updateMOTDDuringStart() + { + /// MOTD when the game is starting (slow TP in progress). + if (enabled) currentMOTD = matchName + I.t("Starting in progress..."); + } + + /** + * Updates the MOTD to the one displayed during the game (includes alive counts). + * <p> + * This need to be called on each death, to update alive counts. + */ + public void updateMOTDDuringGame() + { + if (enabled) + { + if (!p.getGameManager().isGameWithTeams()) + { + /// Solo game running MOTD. {0} = players alive count. + currentMOTD = matchName + I.tn("Game running! {0} player alive.", "Game running! {0} players alive.", p.getGameManager().getAlivePlayersCount(), p.getGameManager().getAlivePlayersCount()); + } + else + { + /// Teams game running MOTD. {0} = players alive count. {1} = teams alive count. Plural based on players count. + currentMOTD = matchName + I.tn("Game running! {0} player alive in {1} team.", "Game running! {0} players alive in {1} teams.", p.getGameManager().getAlivePlayersCount(), p.getGameManager().getAlivePlayersCount(), p.getGameManager().getAliveTeamsCount()); + } + } + } + + /** + * Updates the MOTD after the game. + * + * @param winner The winner. + */ + public void updateMOTDAfterGame(UHTeam winner) + { + if (enabled) + { + if (!p.getGameManager().isGameWithTeams()) + { + /// Game finished MOTD with solo winner ({0} = winner raw name). + currentMOTD = matchName + I.t("Game finished; congratulation to {0} for his victory!", winner.getName()); + } + else + { + /// Game finished MOTD with team winner ({0} = team display name). + currentMOTD = matchName + I.t("Game finished; the team {0} wins this match!", winner.getDisplayName()); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/OfflinePlayersLoader.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/OfflinePlayersLoader.java new file mode 100644 index 0000000..b0384c6 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/OfflinePlayersLoader.java @@ -0,0 +1,305 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.misc; + +import fr.zcraft.zlib.components.worker.Worker; +import fr.zcraft.zlib.components.worker.WorkerCallback; +import fr.zcraft.zlib.components.worker.WorkerRunnable; +import fr.zcraft.zlib.tools.Callback; +import fr.zcraft.zlib.tools.PluginLogger; +import fr.zcraft.zlib.tools.mojang.UUIDFetcher; +import fr.zcraft.zlib.tools.reflection.Reflection; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + + +public class OfflinePlayersLoader extends Worker +{ + private static Map<UUID, OfflinePlayer> offlinePlayers = new HashMap<>(); + + /** + * Returns a list of offline players, including the players who logged in the server and the explicitly + * loaded players. + * + * @return A list of OfflinePlayers. + */ + public static Set<OfflinePlayer> getOfflinePlayers() + { + Set<OfflinePlayer> players = new HashSet<>(); + + players.addAll(offlinePlayers.values()); + Collections.addAll(players, Bukkit.getOfflinePlayers()); + + return Collections.unmodifiableSet(players); + } + + /** + * Retrieves an OfflinePlayer by ID. + * + * Tries to load a logged-in player, then an explicitly loaded player, then + * a server-wide OfflinePlayer. + * + * @param id The player's UUID. + * @return An OfflinePlayer. The retrieved object will never be null but may not + * be loaded with a name and other data if the player never came to the server and + * was not explicitly loaded. + */ + public static OfflinePlayer getOfflinePlayer(UUID id) + { + OfflinePlayer player = Bukkit.getPlayer(id); + if (player == null) player = offlinePlayers.get(id); + if (player == null) player = Bukkit.getOfflinePlayer(id); + + return player; + } + + /** + * Retrieves an OfflinePlayer by name. + * + * Tries to load a logged-in player, then an explicitly loaded player, then + * a server-wide OfflinePlayer. + * + * @param name The player's name. + * @return An OfflinePlayer. {@code null} if no player was found with this name. + */ + public static OfflinePlayer getOfflinePlayer(String name) + { + OfflinePlayer player = null; + + for (Player onlinePlayer : Bukkit.getOnlinePlayers()) + { + if (onlinePlayer.getName().equalsIgnoreCase(name)) + { + player = onlinePlayer; + break; + } + } + + if (player == null) + { + for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) + { + if (offlinePlayer.getName().equalsIgnoreCase(name)) + { + player = offlinePlayer; + break; + } + } + } + + if (player == null) + { + for (OfflinePlayer offlinePlayer : offlinePlayers.values()) + { + if (offlinePlayer.getName().equalsIgnoreCase(name)) + { + player = offlinePlayer; + break; + } + } + } + + return player; + } + + /** + * Loads the given players list in the system, making it available in the players list and to be added in teams. + * + * @param pseudonym A pseudonym. + * @param successCallback A callback called when the process ended. Called with {@code null} if no player was found. + */ + public static void loadPlayer(final String pseudonym, final Callback<OfflinePlayer> successCallback) + { + loadPlayers(Collections.singletonList(pseudonym), new Callback<Map<UUID, OfflinePlayer>>() + { + @Override + public void call(Map<UUID, OfflinePlayer> retrieved) + { + if (successCallback != null) + { + if (retrieved.size() == 1) + successCallback.call(retrieved.values().iterator().next()); + else + successCallback.call(null); + } + } + }); + } + + /** + * Loads the given players list in the system, making it available in the players list and to be added in teams. + * + * @param pseudonyms A list of pseudonyms. + * @param callbackSuccess A callback called when the process ended. + */ + public static void loadPlayers(final List<String> pseudonyms, final Callback<Map<UUID, OfflinePlayer>> callbackSuccess) + { + loadPlayers(pseudonyms, callbackSuccess, new Callback<List<String>>() + { + @Override + public void call(List<String> errors) + { + PluginLogger.error("Unable to retrieve the following names: {0}", StringUtils.join(errors, ", ")); + } + }); + } + + /** + * Loads the given players list in the system, making it available in the players list + * and to be added in teams. + * + * Only works in online mode. In offline mode, the already known players will be sent + * to the success callback and the others to the errors one. Use {@link UUIDFetcher} + * directly if needed. + * + * @param pseudonyms A list of pseudonyms. + * @param callbackSuccess A callback called when the process ended. + */ + public static void loadPlayers(final List<String> pseudonyms, final Callback<Map<UUID, OfflinePlayer>> callbackSuccess, final Callback<List<String>> callbackErrors) + { + final List<String> toRetrieve = new ArrayList<>(pseudonyms); + final Map<UUID, OfflinePlayer> alreadyKnown = new HashMap<>(); + + for (String pseudonym : pseudonyms) + { + OfflinePlayer player = getOfflinePlayer(pseudonym); + if (player != null) + { + alreadyKnown.put(player.getUniqueId(), player); + toRetrieve.remove(pseudonym); + } + } + + if (toRetrieve.size() == 0) + { + if (callbackSuccess != null) callbackSuccess.call(alreadyKnown); + return; + } + + // If the server is in offline mode, we don't even try to load the players, as they will + // not be valid and be unusable. + if (!Bukkit.getOnlineMode()) + { + if (callbackSuccess != null) callbackSuccess.call(alreadyKnown); + if (callbackErrors != null && toRetrieve.size() > 0) callbackErrors.call(toRetrieve); + + return; + } + + submitQuery(new WorkerRunnable<Map<String, UUID>>() + { + @Override + public Map<String, UUID> run() throws Throwable + { + Map<String, UUID> uuids = UUIDFetcher.fetch(toRetrieve); + UUIDFetcher.fetchRemaining(toRetrieve, uuids); + + return uuids; + } + }, new WorkerCallback<Map<String, UUID>>() + { + @Override + public void finished(final Map<String, UUID> result) + { + final Map<UUID, OfflinePlayer> added = new HashMap<>(alreadyKnown); + final Class<?> gameProfileClass; + + try + { + gameProfileClass = Class.forName("com.mojang.authlib.GameProfile"); + } + catch (ClassNotFoundException e) + { + PluginLogger.error("Cannot load GameProfile class required to load OfflinePlayers.", e); + return; + } + + for (Map.Entry<String, UUID> playerProfile : result.entrySet()) + { + String name = playerProfile.getKey(); + UUID uuid = playerProfile.getValue(); + + if (uuid == null) + { + PluginLogger.error("Unable to load the player {0}, skipping.", name); + continue; + } + + try + { + Object profile = Reflection.instantiate(gameProfileClass, uuid, name); + OfflinePlayer player = (OfflinePlayer) Reflection.call(Bukkit.getServer(), "getOfflinePlayer", profile); + + offlinePlayers.put(uuid, player); + added.put(uuid, player); + } + catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) + { + PluginLogger.error("Unable to load the player {0}, skipping.", e, playerProfile.getKey()); + } + } + + if (callbackSuccess != null) callbackSuccess.call(added); + + if (callbackErrors != null) + { + List<String> notRetrieved = new ArrayList<>(); + for (String pseudonym : toRetrieve) + { + if (!result.keySet().contains(pseudonym)) + notRetrieved.add(pseudonym); + } + + if (notRetrieved.size() > 0) callbackErrors.call(notRetrieved); + } + } + + @Override + public void errored(Throwable exception) + { + PluginLogger.error("Unable to load players", exception); + } + }); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java new file mode 100644 index 0000000..f2b1b3c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java @@ -0,0 +1,132 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.misc; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.text.ListHeaderFooter; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + + +public class PlayerListHeaderFooterManager +{ + private final String WAITING_HEADER_PATTERN; + private final String WAITING_FOOTER_PATTERN; + private final String IN_GAME_HEADER_PATTERN; + private final String IN_GAME_FOOTER_PATTERN; + + private String currentHeader = ""; + private String currentFooter = ""; + + + public PlayerListHeaderFooterManager() + { + WAITING_HEADER_PATTERN = UHConfig.PLAYERS_LIST.WAITING_TIME.HEADER.get(); + WAITING_FOOTER_PATTERN = UHConfig.PLAYERS_LIST.WAITING_TIME.FOOTER.get(); + IN_GAME_HEADER_PATTERN = UHConfig.PLAYERS_LIST.IN_GAME_TIME.HEADER.get(); + IN_GAME_FOOTER_PATTERN = UHConfig.PLAYERS_LIST.IN_GAME_TIME.FOOTER.get(); + + updateHeadersFooters(); + } + + + public void updateHeadersFooters() + { + computeHeadersFooter(); + send(); + } + + public void sendTo(Player player) + { + if (!currentHeader.isEmpty() || !currentFooter.isEmpty()) + ListHeaderFooter.sendListHeaderFooter(player, currentHeader, currentFooter); + } + + + private void computeHeadersFooter() + { + if (UHCReloaded.get().getGameManager().isGameStarted()) + { + currentHeader = computeText(IN_GAME_HEADER_PATTERN); + currentFooter = computeText(IN_GAME_FOOTER_PATTERN); + } + else + { + currentHeader = computeText(WAITING_HEADER_PATTERN); + currentFooter = computeText(WAITING_FOOTER_PATTERN); + } + } + + private String computeText(String pattern) + { + return pattern.isEmpty() ? "" : ChatColor.translateAlternateColorCodes('&', replaceTags(pattern)); + } + + /** + * Tags: + * - {title}: contains the scoreboard title (key scoreboard.title). + * - {episodeText}: contains the localized “Episode x” text. + * - {playersText}: contains the localized “x players left” text. + * - {teamsText}: contains the localized “x teams left” text. + * - {episodeNumber}: contains the raw episode number (e.g. “2”). + * - {playersCount}: contains the raw alive players count (e.g. “18”). + * - {teamsCount}: contains the raw alive teams count (e.g. “6”). + * + * @param raw The raw text. + * @return The text, with tags replaced. + */ + private String replaceTags(String raw) + { + return raw + .replace("{title}", UHConfig.SCOREBOARD.TITLE.get()) + + /// Episode in the player list ({episodeText} replacement). {0} = current episode number. + .replace("{episodeText}", I.t("Episode {0}", String.valueOf(UHCReloaded.get().getGameManager().getEpisode()))) + /// Players in the player list ({playersText} replacement). {0} = current alive players count. + .replace("{playersText}", I.tn("{0} player", "{0} players", UHCReloaded.get().getGameManager().getAlivePlayersCount(), UHCReloaded.get().getGameManager().getAlivePlayersCount())) + /// Teams in the player list ({teamsText} replacement). {0} = current alive teams count. + .replace("{teamsText}", I.tn("{0} team", "{0} teams", UHCReloaded.get().getGameManager().getAliveTeamsCount(), UHCReloaded.get().getGameManager().getAliveTeamsCount())) + + .replace("{episodeNumber}", String.valueOf(UHCReloaded.get().getGameManager().getEpisode())) + .replace("{playersCount}", String.valueOf(UHCReloaded.get().getGameManager().getAlivePlayersCount())) + .replace("{teamsCount}", String.valueOf(UHCReloaded.get().getGameManager().getAliveTeamsCount())) + ; + } + + private void send() + { + if (!currentHeader.isEmpty() || !currentFooter.isEmpty()) + ListHeaderFooter.sendListHeaderFooter(currentHeader, currentFooter); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java new file mode 100644 index 0000000..e34885c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java @@ -0,0 +1,150 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.misc; + +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.commands.core.utils.CommandUtils; +import fr.zcraft.zlib.components.i18n.I; +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.List; + + +public class RulesManager +{ + private final boolean DISPLAY_ON_JOIN; + private final boolean DISPLAY_ON_START; + + private final List<String> rules = new ArrayList<>(); + + + public RulesManager() + { + if (UHConfig.RULES.isDefined() && !UHConfig.RULES.RULES.isEmpty() ) + { + DISPLAY_ON_JOIN = UHConfig.RULES.DISPLAY.ON_JOIN.get(); + DISPLAY_ON_START = UHConfig.RULES.DISPLAY.ON_START.get(); + + + // We check if the list is non-empty, i.e. if there is at least a non-empty rule. + boolean empty = true; + + for (String rule : UHConfig.RULES.RULES) + { + if (rule == null) continue; + + rule = rule.trim(); + rules.add(ChatColor.translateAlternateColorCodes('&',rule)); + + if (!rule.isEmpty()) + empty = false; + } + + // If the list is empty, no rules are displayed. We reset the list. + if (empty) rules.clear(); + } + else + { + DISPLAY_ON_JOIN = false; + DISPLAY_ON_START = true; + } + } + + /** + * @return {@code true} if the rules system is enabled + */ + public boolean isEnabled() + { + return rules.size() != 0; + } + + /** + * @return {@code true} if the rules have to be displayed to every joining player. + */ + public boolean displayOnJoin() + { + return isEnabled() && DISPLAY_ON_JOIN; + } + + /** + * @return {@code true} if the rules have to be displayed when the game starts. + */ + public boolean displayOnStart() + { + return isEnabled() && DISPLAY_ON_START; + } + + + /** + * Displays the rules to the given receiver. + * + * @param receiver The receiver. + */ + public void displayRulesTo(CommandSender receiver) + { + CommandUtils.displaySeparator(receiver); + /// Title of the rules box. + receiver.sendMessage(I.t("{red}{bold}Rules and informations")); + + for (String rule : rules) + { + if (rule.isEmpty()) + { + receiver.sendMessage(""); + } + else + { + /// Rule item in the rule box. + receiver.sendMessage(I.t("{darkgray}- {reset}{0}", rule)); + } + } + + CommandUtils.displaySeparator(receiver); + } + + /** + * Broadcasts the rules to the whole server. + */ + public void broadcastRules() + { + for (Player player : Bukkit.getOnlinePlayers()) + { + displayRulesTo(player); + } + + displayRulesTo(Bukkit.getConsoleSender()); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RuntimeCommandsExecutor.java b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RuntimeCommandsExecutor.java new file mode 100644 index 0000000..ff3a76d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/misc/RuntimeCommandsExecutor.java @@ -0,0 +1,280 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.misc; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.task.ScheduledCommandsExecutorTask; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + + +/** + * This will execute the commands to be executed during runtime, as configured in the config.yml file + * or added through the API. + */ +public class RuntimeCommandsExecutor +{ + private UHCReloaded p = null; + + /** + * Stores the commands to be executed later. + * <p> + * The first map (String->HashMap) associates a key to a group of commands launched at the same time.<br> + * The sub-map (Integer->HashSet) associates a delay, in seconds, with a set containing the commands to be + * executed this number of seconds after the call of the {@link #registerCommandsInScheduler(String)} + * method. + */ + private Map<String, HashMap<Integer, HashSet<String>>> scheduled = new HashMap<>(); + + + /** + * The key for the commands executed when the server starts. + */ + public final static String AFTER_SERVER_START = "internal.server-start"; + + /** + * The key for the commands executed after the beginning of the game. + */ + public final static String AFTER_GAME_START = "internal.game-start"; + + /** + * The key for the commands executed after the end of the game. + */ + public final static String AFTER_GAME_END = "internal.game-end"; + + + public RuntimeCommandsExecutor(UHCReloaded plugin) + { + p = plugin; + + importFromConfig("commands.execute-server-start", AFTER_SERVER_START); + importFromConfig("commands.execute-start", AFTER_GAME_START); + importFromConfig("commands.execute-end", AFTER_GAME_END); + } + + /** + * Register the commands registered under the given key in the Bukkit' scheduler. + * <p> + * Delays are from the execution of this method. + * + * @param key The key to schedule. All commands previously registered under this key will be executed. + */ + public void registerCommandsInScheduler(String key) + { + registerCommandsInScheduler(scheduled.get(key)); + } + + /** + * Register the given commands in the Bukkit' scheduler. + * + * Delays are from the execution of this method. + * @param scheduledCommands + */ + private void registerCommandsInScheduler(Map<Integer, HashSet<String>> scheduledCommands) + { + if (scheduledCommands != null) + { + for (Entry<Integer, HashSet<String>> scheduledCommandsStack : scheduledCommands.entrySet()) + { + p.getServer().getScheduler().runTaskLater( + p, + new ScheduledCommandsExecutorTask(p, scheduledCommandsStack.getValue()), + scheduledCommandsStack.getKey() * 20l + ); + } + } + } + + + /** + * Schedules a command. + * <p> + * To schedule a command executed by the plugin, like in the configuration file, you will have + * to use the keys defined as static attributes of this class: + * {@link #AFTER_SERVER_START}, {@link #AFTER_GAME_END} and {@link #AFTER_GAME_START}. + * + * @param key The command will be stored under this key. + * The keys internally used by the plugin start by "{@code internal.}". + * @param command The command to add. + * @param delay The delay (seconds). + */ + public void scheduleCommand(String key, String command, Integer delay) + { + if (!scheduled.containsKey(key)) + { + scheduled.put(key, new HashMap<Integer, HashSet<String>>()); + } + + scheduleCommand(scheduled.get(key), command, delay); + } + + /** + * Schedules a command. + * + * @param scheduledCommands A map containing the scheduled commands, sorted by delay. + * @param command The command to add. + * @param delay The delay (seconds). + */ + private void scheduleCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) + { + HashSet<String> list = scheduledCommands.get(delay); + + if (list == null) + { + list = new HashSet<>(); + scheduledCommands.put(delay, list); + } + + list.add(clearCommandName(command)); + } + + + /** + * Removes the given command from everywhere. + * + * @param key The command will be stored under this key. + * The keys internally used by the plugin start by "{@code internal.}". + * @param command The command. Not case-sensitive. + */ + public void removeScheduledCommand(String key, String command) + { + removeScheduledCommand(scheduled.get(key), command); + } + + /** + * Removes the given command from everywhere. + * + * @param scheduledCommands A map containing the scheduled commands, sorted by delay. + * @param command The command. Not case-sensitive. + */ + private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command) + { + for (HashSet<String> commands : scheduledCommands.values()) + { + for (String scheduledCommand : new HashSet<String>(commands)) + { + if (scheduledCommand.equalsIgnoreCase(clearCommandName(command))) + { + commands.remove(scheduledCommand); + } + } + } + } + + + /** + * Removes the given command from everywhere. + * + * @param key The command will be stored under this key. + * The keys internally used by the plugin start by "{@code internal.}". + * @param command The command. Not case-sensitive. + */ + public void removeScheduledCommand(String key, String command, Integer delay) + { + removeScheduledCommand(scheduled.get(key), command, delay); + } + + /** + * Removes the given command from everywhere. + * + * @param scheduledCommands A map containing the scheduled commands, sorted by delay. + * @param command The command. Not case-sensitive. + */ + private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) + { + HashSet<String> commands = scheduledCommands.get(delay); + + if (commands != null) + { + for (String scheduledCommand : commands) + { + if (scheduledCommand.equalsIgnoreCase(clearCommandName(command))) + { + commands.remove(scheduledCommand); + } + } + } + } + + + /* Utilities */ + + /** + * Imports the commands stored in the configuration. + * + * @param path The path in the config file. + * @param key The command will be stored under this key. + * The keys internally used by the plugin start by "{@code internal.}". + */ + private void importFromConfig(String path, String key) + { + List<Map<?, ?>> rawCommands = p.getConfig().getMapList(path); + + if (rawCommands != null) + { + for (Map<?, ?> rawCommand : rawCommands) + { + String cmd = String.valueOf(rawCommand.get("exec")); + Integer delay; + + if (cmd == null || cmd.isEmpty()) continue; + + try + { + delay = UHUtils.string2Time(String.valueOf(rawCommand.get("delay"))); + } + catch (IllegalArgumentException e) + { + delay = 0; + } + + scheduleCommand(key, cmd, delay); + } + } + } + + + private String clearCommandName(String command) + { + if (command.startsWith("/")) + { + command = command.substring(1); + } + + return command; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java b/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java new file mode 100644 index 0000000..94f1f25 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java @@ -0,0 +1,147 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.protips; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.utils.UHSound; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArraySet; + + +/** + * A ProTip, sent to a player only once. + */ +public class ProTip +{ + private static final UHSound proTipsSound = new UHSound(UHConfig.PROTIPS.SOUND); + + private String text; + private Boolean enabled; + + private Set<UUID> sentTo = new CopyOnWriteArraySet<>(); + + + /** + * @param enabled {@code false} to avoid this ProTip from being sent when {@link #sendTo(Player)} is called. + * @param text The ProTip text. + */ + public ProTip(Boolean enabled, String text) + { + this.text = text; + this.enabled = enabled; + } + + /** + * @param name A name registered in the UHCReloaded config file, used to disable the powerup if needed, following the configuration. + * @param text The ProTip text. + */ + public ProTip(String name, String text) + { + this(UHCReloaded.get().getConfig().getBoolean("protips." + name), text); + } + + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public String getText() + { + return text; + } + + public Boolean isEnabled() + { + return enabled; + } + + + /** + * Checks if this ProTip was sent to this player. + * + * @param id The player's UUID. + * @return {@code true} if already sent. + */ + public Boolean wasSentTo(UUID id) + { + return sentTo.contains(id); + } + + /** + * Checks if this ProTip was sent to this player. + * + * @param player The player. + * @return {@code true} if already sent. + */ + public Boolean wasSentTo(Player player) + { + return wasSentTo(player.getUniqueId()); + } + + + /** + * Sends a ProTip, if this ProTip wasn't sent before to this player. + * + * @param player The receiver of this ProTip. + */ + public void sendTo(Player player) + { + if (!isEnabled() || wasSentTo(player)) + return; + + sentTo.add(player.getUniqueId()); + + /// ProTip invite, displayed before a ProTip. + player.sendMessage(I.t("{darkpurple}ProTip!") + " " + ChatColor.RESET + text); + proTipsSound.play(player); + } + + /** + * Sends a ProTip, if this ProTip wasn't sent before to this player and this player is online. + * + * @param id The receiver of this ProTip. + */ + public void sendTo(UUID id) + { + Player player = Bukkit.getPlayer(id); + if (player != null && player.isOnline()) + sendTo(player); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java b/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java new file mode 100644 index 0000000..602ed75 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java @@ -0,0 +1,89 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.protips; + +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.entity.Player; + +import java.util.UUID; + + +public enum ProTips +{ + LOCK_CHAT(new ProTip("teamchat.lock", I.tc("protip", "{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}."))), + USE_G_COMMAND(new ProTip("teamchat.useGCommand", I.tc("protip", "{gray}You can send a global message using {cc}/g <message>{gray}."))), + USE_T_COMMAND(new ProTip("teamchat.useTCommand", I.tc("protip", "{gray}You can send a team-chat message with {cc}/t <message>{gray}."))), + + CRAFT_GOLDEN_HEAD(new ProTip("crafts.goldenHead", I.tc("protip", "{gray}You can craft golden apples with heads (same recipe with a head instead of an apple)."))), + CRAFT_COMPASS_EASY(new ProTip("crafts.compassEasy", I.tc("protip", "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder."))), + CRAFT_COMPASS_MEDIUM(new ProTip("crafts.compassMedium", I.tc("protip", "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder; in the center, an ender pearl."))), + CRAFT_COMPASS_HARD(new ProTip("crafts.compassHard", I.tc("protip", "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder; in the center, an Eye of Ender."))), + CRAFT_GLISTERING_MELON(new ProTip("crafts.glisteringMelon", I.tc("protip", "{gray}The glistering melon is crafted with a melon and a gold block."))), + + CRAFT_NO_ENCHANTED_GOLDEN_APPLE(new ProTip("crafts.noEnchGoldenApple", I.tc("protip", "{gray}The enchanted golden apple is disabled for this game."))), + + STARTUP_INVINCIBILITY(new ProTip("start.invincibility", I.tc("protip", "{gray}Fallen on a tree? Jump, you have a few seconds left to remain invincible."))); + + + private final ProTip proTip; + + ProTips(ProTip proTip) + { + this.proTip = proTip; + } + + public ProTip get() + { + return proTip; + } + + + /** + * Sends this ProTip, if it wasn't sent before to this player. + * + * @param player The receiver of this ProTip. + */ + public void sendTo(Player player) + { + proTip.sendTo(player); + } + + /** + * Sends this ProTip, if it wasn't sent before to this player and this player is online. + * + * @param id The receiver of this ProTip. + */ + public void sendTo(UUID id) + { + proTip.sendTo(id); + } +} diff --git a/src/main/java/me/azenet/UHPlugin/recipes/RecipeUtil.java b/src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipeUtil.java similarity index 51% rename from src/main/java/me/azenet/UHPlugin/recipes/RecipeUtil.java rename to src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipeUtil.java index f216a2e..123e673 100644 --- a/src/main/java/me/azenet/UHPlugin/recipes/RecipeUtil.java +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipeUtil.java @@ -1,35 +1,52 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". * - * 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. + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. * - * 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. + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/]. + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. */ +package eu.carrade.amaury.UHCReloaded.recipes; -package me.azenet.UHPlugin.recipes; - -import org.bukkit.inventory.*; +import org.bukkit.inventory.FurnaceRecipe; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.ShapedRecipe; +import org.bukkit.inventory.ShapelessRecipe; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Map; + /** * Utility class to compare Bukkit recipes.<br> * Useful for identifying your recipes in events, where recipes are re-generated in a different manner. - * + * * @version R1.3 * @author Digi */ @@ -40,13 +57,13 @@ public class RecipeUtil * If this is used as data value on an ingredient it will accept any data value. */ public static final short DATA_WILDCARD = Short.MAX_VALUE; - + /** * Checks if both recipes are equal.<br> * Compares both ingredients and results.<br> * <br> * NOTE: If both arguments are null it returns true. - * + * * @param recipe1 the first recipe * @param recipe2 the second recipe * @return true if ingredients and results match, false otherwise. @@ -75,71 +92,71 @@ public static boolean areSimilar(Recipe recipe1, Recipe recipe2) { return recipe1 == recipe2 || !(recipe1 == null || recipe2 == null) && match(recipe1, recipe2); } - + private static boolean match(Recipe recipe1, Recipe recipe2) { - if(recipe1 instanceof ShapedRecipe) + if (recipe1 instanceof ShapedRecipe) { - if(!(recipe2 instanceof ShapedRecipe)) + if (!(recipe2 instanceof ShapedRecipe)) { - return false; // if other recipe is not the same type then they're not equal. + return false; // if other recipe is not the same type then they're not equal. } - - ShapedRecipe r1 = (ShapedRecipe)recipe1; - ShapedRecipe r2 = (ShapedRecipe)recipe2; - + + ShapedRecipe r1 = (ShapedRecipe) recipe1; + ShapedRecipe r2 = (ShapedRecipe) recipe2; + // convert both shapes and ingredient maps to common ItemStack array. ItemStack[] matrix1 = shapeToMatrix(r1.getShape(), r1.getIngredientMap()); ItemStack[] matrix2 = shapeToMatrix(r2.getShape(), r2.getIngredientMap()); - - if(!Arrays.equals(matrix1, matrix2)) // compare arrays and if they don't match run another check with one shape mirrored. + + if (!Arrays.equals(matrix1, matrix2)) // compare arrays and if they don't match run another check with one shape mirrored. { - mirrorMatrix(matrix1); - + mirrorMatrix(matrix1); + return Arrays.equals(matrix1, matrix2); } - + return true; // ingredients match. } - else if(recipe1 instanceof ShapelessRecipe) + else if (recipe1 instanceof ShapelessRecipe) { - if(!(recipe2 instanceof ShapelessRecipe)) + if (!(recipe2 instanceof ShapelessRecipe)) { return false; // if other recipe is not the same type then they're not equal. } - - ShapelessRecipe r1 = (ShapelessRecipe)recipe1; - ShapelessRecipe r2 = (ShapelessRecipe)recipe2; - + + ShapelessRecipe r1 = (ShapelessRecipe) recipe1; + ShapelessRecipe r2 = (ShapelessRecipe) recipe2; + // get copies of the ingredient lists List<ItemStack> find = r1.getIngredientList(); List<ItemStack> compare = r2.getIngredientList(); - - if(find.size() != compare.size()) + + if (find.size() != compare.size()) { return false; // if they don't have the same amount of ingredients they're not equal. } - - for(ItemStack item : compare) + + for (ItemStack item : compare) { - if(!find.remove(item)) + if (!find.remove(item)) { return false; // if ingredient wasn't removed (not found) then they're not equal. } } - + return find.isEmpty(); // if there are any ingredients not removed then they're not equal. } - else if(recipe1 instanceof FurnaceRecipe) + else if (recipe1 instanceof FurnaceRecipe) { - if(!(recipe2 instanceof FurnaceRecipe)) + if (!(recipe2 instanceof FurnaceRecipe)) { return false; // if other recipe is not the same type then they're not equal. } - - FurnaceRecipe r1 = (FurnaceRecipe)recipe1; - FurnaceRecipe r2 = (FurnaceRecipe)recipe2; - + + FurnaceRecipe r1 = (FurnaceRecipe) recipe1; + FurnaceRecipe r2 = (FurnaceRecipe) recipe2; + //return (r1.getInput().equals(r2.getInput())); return r1.getInput().getType() == r2.getInput().getType(); } @@ -148,62 +165,66 @@ else if(recipe1 instanceof FurnaceRecipe) throw new IllegalArgumentException("Unsupported recipe type: '" + recipe1 + "', update this class!"); } } - + private static ItemStack[] shapeToMatrix(String[] shape, Map<Character, ItemStack> map) { ItemStack[] matrix = new ItemStack[9]; int slot = 0; - - for(int r = 0; r < shape.length; r++) + + for (int r = 0; r < shape.length; r++) { - for(char col : shape[r].toCharArray()) + for (char col : shape[r].toCharArray()) { matrix[slot] = map.get(col); slot++; } - + slot = ((r + 1) * 3); } - + return matrix; } - + private static void mirrorMatrix(ItemStack[] matrix) { ItemStack tmp; - - for(int r = 0; r < 3; r++) + + for (int r = 0; r < 3; r++) { tmp = matrix[(r * 3)]; matrix[(r * 3)] = matrix[(r * 3) + 2]; matrix[(r * 3) + 2] = tmp; } } - - - + + /** - * Returns the list of the ingredients of the given recipe. - * - * @author Amaury Carrade - * - * @param recipe The recipe to analyze. - * @return A list of the ingredients. - */ - public static List<ItemStack> getListOfIngredients(Recipe recipe) { - List<ItemStack> listOfItems = null; - if(recipe instanceof ShapelessRecipe) { - listOfItems = ((ShapelessRecipe) recipe).getIngredientList(); - } - else { - try { - listOfItems = new LinkedList<ItemStack>(((ShapedRecipe) recipe).getIngredientMap().values()); - } - catch(NullPointerException e) { // If the list of items is null - listOfItems = new LinkedList<ItemStack>(); // empty list - } - } - - return listOfItems; - } + * Returns the list of the ingredients of the given recipe. + * + * @author Amaury Carrade + * + * @param recipe The recipe to analyze. + * @return A list of the ingredients. + */ + public static List<ItemStack> getListOfIngredients(Recipe recipe) + { + List<ItemStack> listOfItems; + if (recipe instanceof ShapelessRecipe) + { + listOfItems = ((ShapelessRecipe) recipe).getIngredientList(); + } + else + { + try + { + listOfItems = new LinkedList<>(((ShapedRecipe) recipe).getIngredientMap().values()); + } + catch (NullPointerException e) // If the list of items is null + { + listOfItems = new LinkedList<>(); // empty list + } + } + + return listOfItems; + } } \ No newline at end of file diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java new file mode 100644 index 0000000..99d322f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java @@ -0,0 +1,532 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.recipes; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import fr.zcraft.zlib.components.gui.GuiUtils; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.SkullType; +import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.ShapedRecipe; +import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.ArrayList; + + +public class RecipesManager +{ + private UHCReloaded p = null; + + private Material compassCentralIngredient = null; + private int compassRecipeType = -1; + + public static final String RECIPE_COMPASS = "compass"; + public static final String RECIPE_GLISTERING_MELON = "glistering"; + public static final String RECIPE_ENCHANTED_GOLDEN_APPLE = "EGA"; + + public static final int COMPASS_DISABLED = 0; + public static final int COMPASS_EASY = 1; + public static final int COMPASS_MEDIUM = 2; + public static final int COMPASS_HARD = 3; + + private String lastFailedRecipe = null; + + + public RecipesManager(UHCReloaded plugin) + { + this.p = plugin; + } + + + /** + * Registers the recipes needed, following the configuration. + */ + public void registerRecipes() + { + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.DO.get()) + { + p.getServer().addRecipe(getGoldenHeadHumanRecipe()); + } + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.DO.get()) + { + p.getServer().addRecipe(getGoldenHeadMonsterRecipe()); + } + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.ADD_LORE.get() || UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.ADD_LORE.get()) + { + p.getServer().addRecipe(getLoreRemoverNormalRecipe()); + p.getServer().addRecipe(getLoreRemoverNotchRecipe()); + } + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_MELON_WITH_GOLD_BLOCK.get()) + { + p.getServer().addRecipe(getGoldenMelonRecipe()); + } + + // Because the compass recipe is "semi-shapeless" (the central part is fixed, but the + // loots can be placed into any configuration), there isn't a registered recipe for it + // (I don't want to register 16 recipes for each difficulty). + // Instead, using the inventoryClickEvent/inventoryDragEvent, we checks manually if the + // recipe is valid. + switch (this.getCompassRecipeType()) + { + case COMPASS_EASY: + compassCentralIngredient = Material.REDSTONE; + break; + case COMPASS_MEDIUM: + compassCentralIngredient = Material.ENDER_PEARL; + break; + case COMPASS_HARD: + compassCentralIngredient = Material.EYE_OF_ENDER; + break; + case COMPASS_DISABLED: + break; + } + } + + /** + * Checks if a recipe is allowed. + * + * @param recipe + * @return True if the recipe is allowed, false else. + */ + public boolean isRecipeAllowed(Recipe recipe) + { + + // Vanilla compass recipe is disabled if the special compass is used. + if (UHConfig.GAMEPLAY_CHANGES.COMPASS.ENABLED.get() && RecipeUtil.areSimilar(recipe, getVanillaCompassRecipe())) + { + this.lastFailedRecipe = RECIPE_COMPASS; + return false; + } + + // Vanilla golden melon recipe is disabled if the craft with a gold block is enabled. + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_MELON_WITH_GOLD_BLOCK.get() && RecipeUtil.areSimilar(recipe, getVanillaGoldenMelonRecipe())) + { + this.lastFailedRecipe = RECIPE_GLISTERING_MELON; + return false; + } + + // If enchanted golden apples are disabled... + // The same technique does not work, this is a workaround + if (UHConfig.GAMEPLAY_CHANGES.GOLDEN_APPLE.DISABLE_NOTCH_APPLES.get()) + { + if (recipe.getResult().getType() == Material.GOLDEN_APPLE) + { + for (ItemStack item : RecipeUtil.getListOfIngredients(recipe)) + { + if (item.getType() == Material.GOLD_BLOCK) + { + // There is a gold block in a recipe for a golden apple - NOPE NOPE NOPE + this.lastFailedRecipe = RECIPE_ENCHANTED_GOLDEN_APPLE; + return false; + } + } + } + } + + // The recipe is allowed. + return true; + } + + /** + * Checks if the recipe is a valid compass recipe. + * <p> + * A valid compass recipe is a recipe with: + * <ul> + * <li> + * in the center, the valid ingredient for the current compass craft + * (redstone, ender pearl or eye of ender); + * </li> + * <li> + * four iron ingots placed like the vanilla compass recipe; + * </li> + * <li> + * in the four corners, a bone, a rotten flesh, a spider eye and a gunpowder, + * placed in any shape. + * </li> + * </ul> + * <p> + * Executed in the {@code onInventoryClick} and {@code onInventoryDrag} events, to allow this to be recognized even if + * the recipe is not registered. + * + * @param matrix The content of the crafting inventory. + * @return true if the recipe is an alternate recipe for the compass. + */ + public boolean isValidCompassRecipe(ItemStack[] matrix) + { + if (matrix.length <= 5) + { + return false; // Small crafting grid + } + + if (this.getCompassRecipeType() == COMPASS_DISABLED) + { + return false; + } + + + // 1: check of the static part (central ingredient + iron) + + Material iron1 = matrix[1].getType(); + Material iron2 = matrix[3].getType(); + Material iron3 = matrix[5].getType(); + Material iron4 = matrix[7].getType(); + Material centralIngredient = matrix[4].getType(); + + if (!(iron1.equals(Material.IRON_INGOT) + && iron2.equals(Material.IRON_INGOT) + && iron3.equals(Material.IRON_INGOT) + && iron4.equals(Material.IRON_INGOT) + && centralIngredient.equals(compassCentralIngredient))) + { + return false; + } + + // 2: check of the dynamic part (loots) + + ArrayList<Material> corners = new ArrayList<>(); + corners.add(matrix[0].getType()); + corners.add(matrix[2].getType()); + corners.add(matrix[6].getType()); + corners.add(matrix[8].getType()); + + return corners.contains(Material.BONE) + && corners.contains(Material.ROTTEN_FLESH) + && corners.contains(Material.SPIDER_EYE) + && corners.contains(Material.SULPHUR); + } + + + /** + * Adds the lore to the golden apples, if needed. + * + * @param recipe The recipe to change. + * @param inventory The crafting inventory (used to access the skull owner) + * @return The modified result (ItemStack) if a change was needed. Null if no change is needed. + */ + public ItemStack addLore(Recipe recipe, CraftingInventory inventory) + { + if ((UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.DO.get() || UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.DO.get()) + && (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.ADD_LORE.get() || UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.ADD_LORE.get()) + && (RecipeUtil.areSimilar(recipe, getGoldenHeadHumanRecipe()) || RecipeUtil.areSimilar(recipe, getGoldenHeadMonsterRecipe()))) + { + ItemStack result = recipe.getResult(); + ItemMeta meta = result.getItemMeta(); + + // Lookup for the head in the recipe + String name = ""; + Boolean wither = true; + + for (ItemStack item : inventory.getContents()) + { + if (item.getType() == Material.SKULL_ITEM && item.getDurability() == (short) SkullType.PLAYER.ordinal()) + { // An human head + SkullMeta sm = (SkullMeta) item.getItemMeta(); + if (sm.hasOwner()) + { // An human head + name = sm.getOwner(); + wither = false; + } + break; + } + } + + if ((wither && UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.ADD_LORE.get()) + || (!wither && UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.ADD_LORE.get())) + { + if (wither) + { + /// Golden head lore for withers + meta.setLore(GuiUtils.generateLore(I.t("Made from the fallen head of a malignant monster"))); + } + else + { + /// Golden head lore for players. {0} = player name. + meta.setLore(GuiUtils.generateLore(I.t("Made from the fallen head of {0}", name))); + } + } + + result.setItemMeta(meta); + return result; + } + + return null; + } + + /** + * Changes the name of the result item of the anti-lore recipe, + * to keep the same name than the original. + * + * @param recipe The recipe. + * @param inventory The crafting inventory. Used to get the name of the item placed in the inventory grid. + * @return The ItemStack if a change was needed; null else. + */ + public ItemStack keepNameOnLoreRemover(Recipe recipe, CraftingInventory inventory) + { + if ((UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.ADD_LORE.get() || UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.ADD_LORE.get()) + && (RecipeUtil.areSimilar(recipe, getLoreRemoverNormalRecipe()) || RecipeUtil.areSimilar(recipe, getLoreRemoverNotchRecipe()))) + { + + ItemStack original = null; + for (int slot = 0; slot <= 9; slot++) + { + original = inventory.getMatrix()[slot]; + if (original.getType() != Material.AIR) + { + break; // Found (because there is only one item in the craft). + } + } + + ItemMeta metaOriginal = original.getItemMeta(); + + if (metaOriginal != null && metaOriginal.hasDisplayName()) + { + ItemStack result = recipe.getResult(); + ItemMeta metaResult = result.getItemMeta(); + + metaResult.setDisplayName(metaOriginal.getDisplayName()); + result.setItemMeta(metaResult); + + return result; + } + + return null; + } + + return null; + } + + + /** + * Returns the current compass recipe. + * + * @return {@link RecipesManager#COMPASS_DISABLED}, {@link RecipesManager#COMPASS_EASY}, + * {@link RecipesManager#COMPASS_MEDIUM} or {@link RecipesManager#COMPASS_HARD}. + */ + public int getCompassRecipeType() + { + if (compassRecipeType != -1) + { + return compassRecipeType; + } + + if (UHConfig.GAMEPLAY_CHANGES.COMPASS.ENABLED.get()) + { + switch (UHConfig.GAMEPLAY_CHANGES.COMPASS.RECIPE.get().toLowerCase()) + { + case "easy": + compassRecipeType = COMPASS_EASY; + break; + + case "hard": + compassRecipeType = COMPASS_HARD; + break; + + default: + compassRecipeType = COMPASS_MEDIUM; + break; + } + } + else + { + compassRecipeType = COMPASS_DISABLED; + } + + return compassRecipeType; + } + + /** + * Returns the recipe that transforms 8 gold ingots and 1 human head into + * a golden apple. + * + * @return The shaped recipe. + */ + public ShapedRecipe getGoldenHeadHumanRecipe() + { + short damage = 0; + /// Item name of a golden head (from a player) + String name = I.tc("player_head", "{aqua}Golden head"); + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.CRAFT_NOTCH_APPLE.get()) + { + damage = 1; + /// Item name of an enchanted golden head (from a player) + name = I.tc("player_head", "{lightpurple}Golden head"); + } + + ItemStack goldenAppleStack = new ItemStack(Material.GOLDEN_APPLE, UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_HUMAN.NUMBER_CRAFTED.get(), damage); + ItemMeta goldenAppleMeta = goldenAppleStack.getItemMeta(); + goldenAppleMeta.setDisplayName(ChatColor.RESET + name); + goldenAppleStack.setItemMeta(goldenAppleMeta); + + ShapedRecipe goldenAppleFromHeadRecipe = new ShapedRecipe(goldenAppleStack); + + goldenAppleFromHeadRecipe.shape("GGG", "GHG", "GGG"); + goldenAppleFromHeadRecipe.setIngredient('G', Material.GOLD_INGOT); + goldenAppleFromHeadRecipe.setIngredient('H', Material.SKULL_ITEM, SkullType.PLAYER.ordinal()); // TODO: deprecated, but no alternative found... + + return goldenAppleFromHeadRecipe; + } + + /** + * Returns the recipe that transforms 8 gold ingots and 1 wither head into + * a golden apple. + * + * @return The shaped recipe. + */ + public ShapedRecipe getGoldenHeadMonsterRecipe() + { + short damage = 0; + /// Item name of a golden head (from a monster) + String name = I.tc("monster_head", "{aqua}Golden head"); + + if (UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.CRAFT_NOTCH_APPLE.get()) + { + damage = 1; + /// Item name of an enchanted golden head (from a monster) + name = I.tc("monster_head", "{lightpurple}Golden head"); + } + + ItemStack goldenAppleStack = new ItemStack(Material.GOLDEN_APPLE, UHConfig.GAMEPLAY_CHANGES.CRAFT_GOLDEN_APPLE_FROM_HEAD.FROM_WITHER.NUMBER_CRAFTED.get(), damage); + ItemMeta goldenAppleMeta = goldenAppleStack.getItemMeta(); + goldenAppleMeta.setDisplayName(ChatColor.RESET + name); + goldenAppleStack.setItemMeta(goldenAppleMeta); + + ShapedRecipe goldenAppleFromWitherHeadRecipe = new ShapedRecipe(goldenAppleStack); + + goldenAppleFromWitherHeadRecipe.shape("GGG", "GHG", "GGG"); + goldenAppleFromWitherHeadRecipe.setIngredient('G', Material.GOLD_INGOT); + goldenAppleFromWitherHeadRecipe.setIngredient('H', Material.SKULL_ITEM, SkullType.WITHER.ordinal()); // TODO: deprecated, but no alternative found... + + return goldenAppleFromWitherHeadRecipe; + } + + /** + * Returns the recipe that transforms one golden apple into one golden apple. + * Used to remove the lore, so two apples from a different head are stackable. + * + * @return The shapeless recipe. + */ + public ShapelessRecipe getLoreRemoverNormalRecipe() + { + ShapelessRecipe goldenAppleLoreRemoverRecipe = new ShapelessRecipe(new ItemStack(Material.GOLDEN_APPLE, 1, (short) 0)); + goldenAppleLoreRemoverRecipe.addIngredient(Material.GOLDEN_APPLE); + + return goldenAppleLoreRemoverRecipe; + } + + /** + * Returns the recipe that transforms one enchanted golden apple into one enchanted + * golden apple. + * Used to remove the lore, so two apples from a different head are stackable. + * + * @return The shapeless recipe. + */ + public ShapelessRecipe getLoreRemoverNotchRecipe() + { + ShapelessRecipe goldenAppleLoreRemoverNotchRecipe = new ShapelessRecipe(new ItemStack(Material.GOLDEN_APPLE, 1, (short) 1)); + goldenAppleLoreRemoverNotchRecipe.addIngredient(Material.GOLDEN_APPLE, 1); + + return goldenAppleLoreRemoverNotchRecipe; + } + + /** + * Returns the recipe that transforms one melon and one gold block into a golden melon. + * + * @return The shapeless recipe. + */ + public ShapelessRecipe getGoldenMelonRecipe() + { + ShapelessRecipe goldenMelonRecipe = new ShapelessRecipe(new ItemStack(Material.SPECKLED_MELON)); + goldenMelonRecipe.addIngredient(1, Material.GOLD_BLOCK); + goldenMelonRecipe.addIngredient(1, Material.MELON); + + return goldenMelonRecipe; + } + + /** + * Returns the vanilla recipe for the compass. + * + * @return The shaped recipe. + */ + public ShapedRecipe getVanillaCompassRecipe() + { + ShapedRecipe vanillaCompassRecipe = new ShapedRecipe(new ItemStack(Material.COMPASS)); + vanillaCompassRecipe.shape(" I ", "IRI", " I "); + + vanillaCompassRecipe.setIngredient('I', Material.IRON_INGOT); + vanillaCompassRecipe.setIngredient('R', Material.REDSTONE); + + return vanillaCompassRecipe; + } + + /** + * Returns the vanilla recipe for the golden melon. + * + * @return The shaped recipe. + */ + public ShapedRecipe getVanillaGoldenMelonRecipe() + { + ShapedRecipe vanillaGoldenMelonRecipe = new ShapedRecipe(new ItemStack(Material.SPECKLED_MELON)); + vanillaGoldenMelonRecipe.shape("GGG", "GMG", "GGG"); + + vanillaGoldenMelonRecipe.setIngredient('G', Material.GOLD_NUGGET); + vanillaGoldenMelonRecipe.setIngredient('M', Material.MELON); + + return vanillaGoldenMelonRecipe; + } + + + /** + * Returns the last failed recipe. + * + * Use {@link RecipesManager#RECIPE_COMPASS}, {@link RecipesManager#RECIPE_GLISTERING_MELON} and + * {@link RecipesManager#RECIPE_ENCHANTED_GOLDEN_APPLE} to get the type of the failed recipe. + * + * @return the lastFailedRecipe + */ + public String getLastFailedRecipe() + { + return lastFailedRecipe; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java new file mode 100644 index 0000000..1380c0e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java @@ -0,0 +1,389 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.scoreboard; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.borders.worldborders.WorldBorder; +import eu.carrade.amaury.UHCReloaded.game.UHGameManager; +import eu.carrade.amaury.UHCReloaded.misc.Freezer; +import eu.carrade.amaury.UHCReloaded.teams.UHTeam; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.scoreboard.Sidebar; +import fr.zcraft.zlib.components.scoreboard.SidebarMode; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + + +public class GameSidebar extends Sidebar +{ + private final UHGameManager gameManager; + private final WorldBorder border; + + private final boolean EPISODES_ENABLED; + private final boolean EPISODES_IN_SIDEBAR; + private final boolean PLAYERS_IN_SIDEBAR; + private final boolean TEAMS_IN_SIDEBAR; + private final boolean BORDER_IN_SIDEBAR; + private final boolean KILLS_IN_SIDEBAR; + private final boolean TIMER_IN_SIDEBAR; + private final boolean FREEZE_STATUS_IN_SIDEBAR; + + private final boolean OWN_TEAM_IN_SIDEBAR; + private final String OWN_TEAM_TITLE_COLOR; + private final boolean OWN_TEAM_TITLE_IS_NAME; + private final boolean OWN_TEAM_DISPLAY_HEARTS; + private final boolean OWN_TEAM_COLOR_WHOLE_NAME; + private final boolean OWN_TEAM_STRIKE_DEAD_PLAYERS; + private final boolean OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC; + private final String OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX; + private final boolean OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY; + private final double OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED; + + private final boolean BORDER_DISPLAY_DIAMETER; + + private final String FROOZEN_NULL_TIMER_TEXT; + private final String HEART = "\u2764"; + + private final String sidebarTitle; + private final List<String> sidebarTop = new ArrayList<>(); + private final List<String> sidebarBorder = new ArrayList<>(); + private final List<String> sidebarTimers = new ArrayList<>(); + + + public GameSidebar() + { + gameManager = UHCReloaded.get().getGameManager(); + border = UHCReloaded.get().getBorderManager().getBorderProxy(); + + EPISODES_ENABLED = UHConfig.EPISODES.ENABLED.get(); + EPISODES_IN_SIDEBAR = UHConfig.SCOREBOARD.EPISODE.get(); + PLAYERS_IN_SIDEBAR = UHConfig.SCOREBOARD.PLAYERS.get(); + TEAMS_IN_SIDEBAR = UHConfig.SCOREBOARD.TEAMS.get(); + BORDER_IN_SIDEBAR = UHConfig.SCOREBOARD.BORDER.DISPLAYED.get(); + KILLS_IN_SIDEBAR = UHConfig.SCOREBOARD.KILLS.get(); + TIMER_IN_SIDEBAR = UHConfig.SCOREBOARD.TIMER.get(); + FREEZE_STATUS_IN_SIDEBAR = UHConfig.SCOREBOARD.FREEZE_STATUS.get(); + + OWN_TEAM_IN_SIDEBAR = UHConfig.SCOREBOARD.OWN_TEAM.ENABLED.get(); + OWN_TEAM_TITLE_COLOR = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.OWN_TEAM.TITLE.COLOR.get()); + OWN_TEAM_TITLE_IS_NAME = UHConfig.SCOREBOARD.OWN_TEAM.TITLE.USE_TEAM_NAME.get(); + OWN_TEAM_DISPLAY_HEARTS = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_HEARTS.get(); + OWN_TEAM_COLOR_WHOLE_NAME = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.COLOR_NAME.get(); + OWN_TEAM_STRIKE_DEAD_PLAYERS = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.STRIKE_DEAD_PLAYERS.get(); + OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.LOGIN_STATE.ITALIC.get(); + OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.LOGIN_STATE.SUFFIX.get()); + OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY = UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_MET_PLAYERS_ONLY.ENABLED.get(); + OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED = Math.pow(UHConfig.SCOREBOARD.OWN_TEAM.CONTENT.DISPLAY_MET_PLAYERS_ONLY.DISPLAYED_WHEN_CLOSER_THAN.get(), 2); + + BORDER_DISPLAY_DIAMETER = UHConfig.SCOREBOARD.BORDER.DISPLAY_DIAMETER.get(); + + FROOZEN_NULL_TIMER_TEXT = new UHTimer("").toString(); + + setAsync(true); + setAutoRefreshDelay(20); + setContentMode(SidebarMode.PER_PLAYER); + + sidebarTitle = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.TITLE.get()); + } + + @Override + public void preRender() + { + sidebarTop.clear(); + sidebarBorder.clear(); + sidebarTimers.clear(); + + // Top sidebar + + if (EPISODES_ENABLED && EPISODES_IN_SIDEBAR) + { + /// Current episode in the sidebar + sidebarTop.add(I.t("{gray}Episode {white}{0}", + String.valueOf(gameManager.isGameStarted() ? gameManager.getEpisode() : 0) + )); + } + + if (!gameManager.isGameStarted()) + { + if (PLAYERS_IN_SIDEBAR) + /// Players alive in the sidebar + sidebarTop.add(I.tn("{white}{0}{gray} player", "{white}{0}{gray} players", Bukkit.getOnlinePlayers().size(), Bukkit.getOnlinePlayers().size())); + } + else + { + if (gameManager.isGameWithTeams() && EPISODES_ENABLED && EPISODES_IN_SIDEBAR) + sidebarTop.add(""); + + if (PLAYERS_IN_SIDEBAR) + /// Players alive in the sidebar + sidebarTop.add(I.tn("{white}{0}{gray} player", "{white}{0}{gray} players", gameManager.getAlivePlayersCount(), gameManager.getAlivePlayersCount())); + + if (gameManager.isGameWithTeams() && TEAMS_IN_SIDEBAR) + /// Teams alive in the sidebar + sidebarTop.add(I.tn("{white}{0}{gray} team", "{white}{0}{gray} teams", gameManager.getAliveTeamsCount(), gameManager.getAliveTeamsCount())); + } + + + // Border part of the sidebar + + if (gameManager.isGameStarted()) + { + insertBorder(sidebarBorder); + } + + + // Timers part of the sidebar + + insertTimers(sidebarTimers); + + if (TIMER_IN_SIDEBAR) + { + if (!gameManager.isGameStarted()) + sidebarTimers.add(FROOZEN_NULL_TIMER_TEXT); + else + { + final UHTimer mainTimer = UHCReloaded.get().getTimerManager().getMainTimer(); + if (mainTimer != null) sidebarTimers.add(mainTimer.toString()); + } + } + } + + @Override + public List<String> getContent(Player player) + { + List<String> sidebar = new ArrayList<>(); + + sidebar.addAll(sidebarTop); + sidebar.add(""); + + if (OWN_TEAM_IN_SIDEBAR && gameManager.isGameStarted() && gameManager.isGameWithTeams()) + { + UHTeam team = UHCReloaded.get().getTeamManager().getTeamForPlayer(player); + + if (team != null) + { + sidebar.add( + (OWN_TEAM_TITLE_COLOR.isEmpty() ? team.getColor().toChatColor() : OWN_TEAM_TITLE_COLOR) + /// Title of the team section in the sidebar + + (OWN_TEAM_TITLE_IS_NAME ? ChatColor.BOLD + team.getName() : I.t("{bold}Your team")) + ); + + Location playerLocation = player.getLocation(); + + for (UUID teamMember : team.getPlayersUUID()) + { + SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(teamMember); + + // If enabled, we check if the player was already met or is close to this player. + // Only if the damages are on (= 30 seconds after the game start) to avoid false close while + // teleporting. + if(OWN_TEAM_DISPLAY_MET_PLAYERS_ONLY) + { + if(!(teamMember.equals(player.getUniqueId()) || cache.getTeammatesDisplayed().contains(teamMember))) + { + if (gameManager.isGameStarted() && gameManager.isTakingDamage()) + { + if (gameManager.isPlayerDead(teamMember)) + continue; // dead (spectators don't have to be displayed in the sidebar). + + Player teammate = Sidebar.getPlayerAsync(teamMember); + if (teammate == null) + continue; // offline + + + Location teammateLocation = teammate.getLocation(); + + // Check if the players are close + if (teammateLocation.getWorld().equals(playerLocation.getWorld())) + { + final double distanceSquared = teammateLocation.distanceSquared(playerLocation); + if (distanceSquared <= OWN_TEAM_DISPLAY_MET_PLAYERS_MIN_DISTANCE_SQUARED) + cache.getTeammatesDisplayed().add(teamMember); + else + continue; // Too far, skipped + } + else + { + continue; // Too far, skipped + } + } + else + { + continue; + } + } + } + + final String strike = OWN_TEAM_STRIKE_DEAD_PLAYERS && !cache.isAlive() ? ChatColor.STRIKETHROUGH.toString() : ""; + final ChatColor aliveColor = cache.isAlive() ? ChatColor.WHITE : ChatColor.GRAY; + + final String heart = OWN_TEAM_DISPLAY_HEARTS ? cache.getHealthColor() + strike + HEART + " " : ""; + final String name = (OWN_TEAM_COLOR_WHOLE_NAME ? cache.getHealthColor() : aliveColor) + + strike + + (OWN_TEAM_DISPLAY_LOGIN_STATE_ITALIC && !cache.isOnline() ? ChatColor.ITALIC : "") + + cache.getPlayerName() + + (!cache.isOnline() ? ChatColor.RESET + "" + (OWN_TEAM_COLOR_WHOLE_NAME ? cache.getHealthColor() : aliveColor) + " " + OWN_TEAM_DISPLAY_LOGIN_STATE_SUFFIX : ""); + + sidebar.add(heart + name); + } + + sidebar.add(""); + } + } + + sidebar.addAll(sidebarBorder); + + if (KILLS_IN_SIDEBAR && gameManager.isGameStarted()) + { + SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId()); + + /// Kills count in the sidebar + sidebar.add(I.tn("{white}{0}{gray} player killed", "{white}{0}{gray} players killed", cache.getPlayersKilled().size(), cache.getPlayersKilled().size())); + sidebar.add(""); + } + + sidebar.addAll(sidebarTimers); + + if (FREEZE_STATUS_IN_SIDEBAR) + { + insertFreezeStatus(sidebar, player); + } + + return sidebar; + } + + @Override + public String getTitle(Player player) + { + return sidebarTitle; + } + + + /** + * Inserts the border status in the given list, to be displayed in the sidebar. + * + * @param sidebar The list representing the sidebar's content. + */ + private void insertBorder(List<String> sidebar) + { + if (BORDER_IN_SIDEBAR) + { + /// Title of the border section in the sidebar + sidebar.add(I.t("{blue}{bold}Border")); + + int diameter = (int) Math.ceil(border.getDiameter()); + + if (BORDER_DISPLAY_DIAMETER || border.getShape() == MapShape.CIRCULAR) + { + if (border.getShape() == MapShape.SQUARED) + /// Border diameter for a squared map in the sidebar + sidebar.add(I.tn("{white}{0} block wide", "{white}{0} blocks wide", diameter, diameter)); + else + /// Border diameter for a circular map in the sidebar + sidebar.add(I.tn("{gray}Diameter: {white}{0} block", "{gray}Diameter: {white}{0} blocks", diameter, diameter)); + } + else + { + Location center = border.getCenter(); + int radius = (int) Math.ceil(diameter / 2); + + int minX = center.getBlockX() - radius; + int maxX = center.getBlockX() + radius; + int minZ = center.getBlockZ() - radius; + int maxZ = center.getBlockZ() + radius; + + // Same min & max, we can display both at once + if (minX == minZ && maxX == maxZ) + { + /// Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +500". {0} = minimal coord, {1} = maximal coord. + sidebar.add(I.t("{white}{0} {1}", UHUtils.integerToStringWithSign(minX), UHUtils.integerToStringWithSign(maxZ))); + } + else + { + /// Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +500". {0} = minimal coord, {1} = maximal coord. + sidebar.add(I.t("{gray}X: {white}{0} {1}", UHUtils.integerToStringWithSign(minX), UHUtils.integerToStringWithSign(maxX))); + /// Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +500". {0} = minimal coord, {1} = maximal coord. + sidebar.add(I.t("{gray}Z: {white}{0} {1}", UHUtils.integerToStringWithSign(minZ), UHUtils.integerToStringWithSign(maxZ))); + } + } + + sidebar.add(""); + } + } + + /** + * Inserts the timers in the given list, to be displayed in the sidebar, at the bottom of the + * list. + * + * @param sidebar The list representing the sidebar's content. + */ + private void insertTimers(List<String> sidebar) + { + for (UHTimer timer : UHCReloaded.get().getTimerManager().getTimers()) + { + if (timer.isDisplayed()) + { + sidebar.add(timer.getDisplayName()); + sidebar.add(timer.toString()); + sidebar.add(""); + } + } + } + + /** + * Inserts the « frozen » text at the bottom of the list, if active globally or for the given + * player. + * + * @param sidebar The list representing the sidebar's content. + */ + private void insertFreezeStatus(List<String> sidebar, Player player) + { + final Freezer freezer = UHCReloaded.get().getFreezer(); + + if ((freezer.getGlobalFreezeState() && !freezer.isHiddenFreeze()) || freezer.isPlayerFrozen(player)) + { + sidebar.add(""); + /// Notice displayed at the bottom of the sidebar if the game is paused (/uh freeze all). + sidebar.add(I.t("{darkaqua}Game frozen")); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardListener.java b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardListener.java new file mode 100644 index 0000000..e5f8b0b --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardListener.java @@ -0,0 +1,131 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.scoreboard; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.events.UHPlayerDeathEvent; +import eu.carrade.amaury.UHCReloaded.events.UHPlayerResurrectedEvent; +import org.bukkit.Bukkit; +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.EntityDamageEvent; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; + + +public class ScoreboardListener implements Listener +{ + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerJoin(PlayerJoinEvent ev) + { + SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(ev.getPlayer().getUniqueId()); + + cache.updateName(ev.getPlayer().getName()); + cache.updateOnlineStatus(true); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent ev) + { + onPlayerQuit(ev.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerKickEvent ev) + { + onPlayerQuit(ev.getPlayer()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerRegainHealth(EntityRegainHealthEvent ev) + { + if(ev.getEntity() instanceof Player) + onPlayerHealthChange((Player) ev.getEntity()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerLoseHealth(EntityDamageEvent ev) + { + if(ev.getEntity() instanceof Player) + onPlayerHealthChange((Player) ev.getEntity()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerDeath(UHPlayerDeathEvent ev) + { + onPlayerHealthChange(ev.getPlayer()); + + if (ev.getPlayerDeathEvent().getEntity().getKiller() != null) + UHCReloaded.get().getScoreboardManager() + .getSidebarPlayerCache(ev.getPlayerDeathEvent().getEntity().getKiller().getUniqueId()) + .getPlayersKilled().add(ev.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerResurrect(UHPlayerResurrectedEvent ev) + { + onPlayerHealthChange(ev.getPlayer()); + + for (SidebarPlayerCache cache : UHCReloaded.get().getScoreboardManager().getAllSidebarPlayerCache().values()) + { + if(cache.getPlayersKilled().remove(ev.getPlayer().getUniqueId())) + break; + } + } + + private void onPlayerQuit(Player player) + { + UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId()).updateOnlineStatus(false); + } + + private void onPlayerHealthChange(final Player player) + { + // One tick later to use the updated health value. + Bukkit.getScheduler().runTaskLater(UHCReloaded.get(), new Runnable() { + @Override + public void run() + { + SidebarPlayerCache cache = UHCReloaded.get().getScoreboardManager().getSidebarPlayerCache(player.getUniqueId()); + + if(UHCReloaded.get().getGameManager().isPlayerDead(player.getUniqueId())) + cache.updateHealth(0d); + + else + cache.updateHealth(player.getHealth()); + } + }, 1l); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardManager.java new file mode 100644 index 0000000..b1d5de1 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/ScoreboardManager.java @@ -0,0 +1,193 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.scoreboard; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import fr.zcraft.zlib.components.scoreboard.Sidebar; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Criterias; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + + +public class ScoreboardManager +{ + private UHCReloaded p; + + private Map<UUID, SidebarPlayerCache> sidebarCache = new ConcurrentHashMap<>(); + + private final Scoreboard sb; + private Sidebar sidebar = null; + + + public ScoreboardManager(UHCReloaded p) + { + this.p = p; + this.sb = Bukkit.getServer().getScoreboardManager().getNewScoreboard(); + + UHCReloaded.get().getServer().getPluginManager().registerEvents(new ScoreboardListener(), UHCReloaded.get()); + + + // Initialization of the scoreboard (match info in the sidebar) + if (UHConfig.SCOREBOARD.ENABLED.get()) + { + sidebar = new GameSidebar(); + + for (Player player : Bukkit.getOnlinePlayers()) + sidebar.addRecipient(player); + + sidebar.runAutoRefresh(true); + } + + // Initialization of the scoreboard (health in players' list) + if (UHConfig.SCOREBOARD.HEALTH.get()) + { + Objective healthObjective = sb.registerNewObjective("Health", Criterias.HEALTH); + healthObjective.setDisplayName("Health"); + healthObjective.setDisplaySlot(DisplaySlot.PLAYER_LIST); + + // Sometimes, the health is initialized to 0. This is used to fix this. + updateHealthScore(); + } + else + { + sb.clearSlot(DisplaySlot.PLAYER_LIST); // Just in case + } + + // Initialization of the sidebar cache + for (Player player : Bukkit.getOnlinePlayers()) + { + getSidebarPlayerCache(player.getUniqueId()); // Initializes the object. + } + } + + + /** + * Updates the health score for all players. + */ + public void updateHealthScore() + { + for (final Player player : p.getServer().getOnlinePlayers()) + { + updateHealthScore(player); + } + } + + /** + * Updates the health score for the given player. + * + * @param player The player to update. + */ + public void updateHealthScore(final Player player) + { + if (player.getHealth() != 1d) // Prevents killing the player + { + player.setHealth(player.getHealth() - 1); + + Bukkit.getScheduler().runTaskLater(p, new Runnable() + { + @Override + public void run() + { + if (player.getHealth() <= 19d) // Avoids an IllegalArgumentException + { + player.setHealth(player.getHealth() + 1); + } + } + }, 3L); + } + } + + /** + * Tells the player's client to use this scoreboard. + * + * @param p The player. + */ + public void setScoreboardForPlayer(Player p) + { + p.setScoreboard(sb); + sidebar.addRecipient(p); + } + + /** + * Returns the title of the scoreboard, truncated at 32 characters. + * + * @return The name + */ + public String getScoreboardName() + { + String s = ChatColor.translateAlternateColorCodes('&', UHConfig.SCOREBOARD.TITLE.get()); + return s.substring(0, Math.min(s.length(), 32)); + } + + /** + * Returns the internal scoreboard. + * + * @return The internal scoreboard. + */ + public Scoreboard getScoreboard() + { + return sb; + } + + /** + * Returns the cached data about the given player. + * + * @param id The player's UUID. + * @return The cached data, created on the fly if needed. + */ + public SidebarPlayerCache getSidebarPlayerCache(UUID id) + { + SidebarPlayerCache cache = sidebarCache.get(id); + + if(cache != null) + return cache; + + cache = new SidebarPlayerCache(id); + + sidebarCache.put(id, cache); + return cache; + } + + public Map<UUID, SidebarPlayerCache> getAllSidebarPlayerCache() + { + return sidebarCache; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/SidebarPlayerCache.java b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/SidebarPlayerCache.java new file mode 100644 index 0000000..f8307c1 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/SidebarPlayerCache.java @@ -0,0 +1,160 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.scoreboard; + +import eu.carrade.amaury.UHCReloaded.misc.OfflinePlayersLoader; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.scoreboard.Sidebar; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArraySet; + + +/** + * This class stores the data displayed in the sidebar for a player, like the color, the health, the name... + */ +public class SidebarPlayerCache +{ + private UUID playerId; + + private String playerName; + private ChatColor healthColor = ChatColor.WHITE; + + private boolean isOnline; + private boolean isAlive; + + private Set<UUID> playersKilled = new CopyOnWriteArraySet<>(); + private Set<UUID> teammatesDisplayed = new CopyOnWriteArraySet<>(); + + + public SidebarPlayerCache(UUID id) + { + playerId = id; + + Player player = Sidebar.getPlayerAsync(id); + + if(player != null) + { + playerName = player.getName(); + isOnline = true; + updateHealth(player.getHealth()); + } + else + { + playerName = null; + isOnline = false; + } + } + + public void updateName(String name) + { + playerName = name; + } + + public void updateHealth(double health) + { + if (health <= 0) + healthColor = ChatColor.GRAY; + else if (health <= 4.1) + healthColor = ChatColor.DARK_RED; + else if (health <= 8.1) + healthColor = ChatColor.RED; + else if (health <= 12.1) + healthColor = ChatColor.YELLOW; + else if (health <= 16.1) + healthColor = ChatColor.GREEN; + else + healthColor = ChatColor.DARK_GREEN; + + isAlive = (health > 0); + } + + public void updateOnlineStatus(boolean isOnline) + { + this.isOnline = isOnline; + } + + public void addKill(UUID id) + { + playersKilled.add(id); + } + + public UUID getPlayerId() + { + return playerId; + } + + public String getPlayerName() + { + if (playerName != null && !playerName.isEmpty()) + return playerName; + + OfflinePlayer player = OfflinePlayersLoader.getOfflinePlayer(playerId); + if (player != null && player.getName() != null && !player.getName().isEmpty()) + { + playerName = player.getName(); + return playerName; + } + + /// Default nick name when a player cannot be recognized. + return I.t("Unknown"); + } + + public ChatColor getHealthColor() + { + return healthColor; + } + + public boolean isOnline() + { + return isOnline; + } + + public boolean isAlive() + { + return isAlive; + } + + public Set<UUID> getTeammatesDisplayed() + { + return teammatesDisplayed; + } + + public Set<UUID> getPlayersKilled() + { + return playersKilled; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/Generator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/Generator.java new file mode 100644 index 0000000..40d4736 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/Generator.java @@ -0,0 +1,119 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.spawns; + + +import eu.carrade.amaury.UHCReloaded.spawns.generators.CircularSpawnPointsGenerator; +import eu.carrade.amaury.UHCReloaded.spawns.generators.GridSpawnPointsGenerator; +import eu.carrade.amaury.UHCReloaded.spawns.generators.RandomSpawnPointsGenerator; +import eu.carrade.amaury.UHCReloaded.spawns.generators.SpawnPointsGenerator; +import fr.zcraft.zlib.tools.PluginLogger; +import fr.zcraft.zlib.tools.reflection.Reflection; + +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; + + +public enum Generator +{ + /** + * Spawn points generated randomly. + */ + RANDOM(RandomSpawnPointsGenerator.class), + + /** + * Spawn points generated following the shape of a grid, + * with concentric squares (starting from the largest square). + */ + GRID(GridSpawnPointsGenerator.class), + + /** + * Spawn points generated on concentric circles (starting from the + * largest circle). + */ + CIRCULAR(CircularSpawnPointsGenerator.class); + + + private Class<? extends SpawnPointsGenerator> generatorClass; + + /** + * @param generatorClass The generator. + */ + Generator(Class<? extends SpawnPointsGenerator> generatorClass) + { + this.generatorClass = generatorClass; + } + + /** + * Returns a generator based on his name. + * + * <p>Not case sensitive.</p> + * + * @param name The name. + * @return The Generator, or null if not found. + */ + public static Generator fromString(String name) + { + try + { + return Generator.valueOf(name.trim().toUpperCase()); + } + catch (IllegalArgumentException e) + { + return null; + } + } + + /** + * Returns a new instance of the generator. + * + * @return The instance. + */ + public SpawnPointsGenerator getInstance() + { + try + { + return (SpawnPointsGenerator) Reflection.instantiate(generatorClass); + } + catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) + { + PluginLogger.log(Level.SEVERE, "Cannot instantiate the spawn points generator: invalid class (missing constructor?): " + generatorClass.getName(), e.getCause()); + return null; + } + catch (InvocationTargetException e) + { + PluginLogger.log(Level.SEVERE, "Error during the spawn points generator instantiation: " + generatorClass.getName(), e.getCause()); + return null; + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java new file mode 100644 index 0000000..9582335 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java @@ -0,0 +1,305 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.spawns; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.UnknownGeneratorException; +import eu.carrade.amaury.UHCReloaded.spawns.generators.SpawnPointsGenerator; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.World.Environment; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import org.bukkit.util.Vector; + + +public class SpawnsManager +{ + private final boolean AVOID_WATER; + + private UHCReloaded p; + private LinkedList<Location> spawnPoints = new LinkedList<>(); + + + public SpawnsManager(UHCReloaded plugin) + { + this.p = plugin; + + AVOID_WATER = UHConfig.MAP.SPAWN_POINTS.DONT_GENERATE_ABOVE_WATER.get(); + } + + /** + * Adds a spawn point at (x;z) in the default world. + * + * @param vec The vector representing the X and Z coordinates. + */ + public void addSpawnPoint(final Vector vec) + { + addSpawnPoint(p.getServer().getWorlds().get(0), vec.getX(), vec.getZ()); + } + + /** + * Adds a spawn point at (x;z) in the default world. + * + * @param x The X coordinate. + * @param z The Z coordinate. + */ + public void addSpawnPoint(final Double x, final Double z) + { + addSpawnPoint(p.getServer().getWorlds().get(0), x, z); + } + + /** + * Adds a spawn point at (x;z) in the given world. + * + * @param world The world. + * @param x The X coordinate. + * @param z The Z coordinate. + */ + public void addSpawnPoint(final World world, final Double x, final Double z) + { + addSpawnPoint(new Location(world, x, 0, z)); + } + + /** + * Adds a spawn point from a location. + * + * @param location The location. Cloned, so you can use the same location object with + * modifications between two calls. + * + * @throws RuntimeException If the spawn point is in the Nether and no safe spot was + * found. + * @throws IllegalArgumentException If the spawn point is out of the current border. + */ + public void addSpawnPoint(final Location location) + { + Location spawnPoint = location.clone(); + + // Initial fall, except in the nether. + if (!(spawnPoint.getWorld().getEnvironment() == Environment.NETHER)) + { + spawnPoint.setY(location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()) + 120); + } + else + { + Location safeSpot = UHUtils.searchSafeSpot(location); + if (safeSpot == null) + { + throw new RuntimeException("Unable to find a safe spot to set the spawn point " + location.toString()); + } + + spawnPoint.setY(safeSpot.getY()); + } + + if (!p.getBorderManager().isInsideBorder(spawnPoint)) + { + throw new IllegalArgumentException("The given spawn location is outside the current border"); + } + + spawnPoints.add(spawnPoint); + } + + /** + * Returns the registered spawn points. + * + * @return The spawn points. + */ + public List<Location> getSpawnPoints() + { + return spawnPoints; + } + + /** + * Removes all spawn points with the same coordinates as the given location object (X, Z, + * world). + * + * @param location The location to be removed. + * @param precise If true, only the spawn points at the exact same location will be removed. + * Else, the points in the same block. + * + * @return true if something were removed. + */ + public boolean removeSpawnPoint(Location location, boolean precise) + { + List<Location> toRemove = new LinkedList<>(); + + for (Location spawn : getSpawnPoints()) + { + if (location.getWorld().equals(spawn.getWorld())) + { + if (precise + && location.getX() == spawn.getX() + && location.getZ() == spawn.getZ()) + { + toRemove.add(spawn); + } + else if (!precise + && location.getBlockX() == spawn.getBlockX() + && location.getBlockZ() == spawn.getBlockZ()) + { + toRemove.add(spawn); + } + } + } + + for (Location spawnToRemove : toRemove) + { + // Used to remove all occurrences of the spawn point + while (spawnPoints.remove(spawnToRemove)) + ; + } + + return toRemove.size() != 0; + } + + /** + * Removes all registered spawn points. + * + * CANNOT BE CANCELLED. + */ + public void reset() + { + spawnPoints.clear(); + } + + + /** + * Imports spawn points from the configuration. + * + * @return The number of spawn points imported. + */ + public int importSpawnPointsFromConfig() + { + int spawnCount = 0; + + for (Vector position: UHConfig.SPAWN_POINTS) + { + addSpawnPoint(position); + ++spawnCount; + } + + return spawnCount; + } + + + /** + * Generates spawn points with the given generator. + * + * @param generatorName The generator to use. + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will + * be generated.<br> This is limited by the size of the + * map. This will be seen as the diameter of a circular + * or of a squared map, following the shape of the world + * set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the + * region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the + * region where the points will be generated. + * + * @throws CannotGenerateSpawnPointsException In case of fail. + * @throws UnknownGeneratorException If no generator was found by the given name. + */ + public void generateSpawnPoints(String generatorName, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException, UnknownGeneratorException + { + Generator generator = Generator.fromString(generatorName); + if (generator != null) + { + generateSpawnPoints(generator, world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter); + } + else + { + throw new UnknownGeneratorException("The generator '" + generatorName + "' does not exists."); + } + } + + /** + * Generates spawn points with the given generator. + * + * @param generator The generator to use. + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will + * be generated.<br> This is limited by the size of the + * map. This will be seen as the diameter of a circular + * or of a squared map, following the shape of the world + * set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the + * region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the + * region where the points will be generated. + * + * @throws CannotGenerateSpawnPointsException In case of fail. + */ + public void generateSpawnPoints(Generator generator, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException + { + generateSpawnPoints(generator.getInstance(), world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter); + } + + /** + * Generates spawn points with the given generator. + * + * @param generator The generator to use. + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will + * be generated.<br> This is limited by the size of the + * map. This will be seen as the diameter of a circular + * or of a squared map, following the shape of the world + * set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the + * region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the + * region where the points will be generated. + * + * @throws CannotGenerateSpawnPointsException In case of fail. + */ + public void generateSpawnPoints(SpawnPointsGenerator generator, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException + { + Set<Location> spawnPoints = generator.generate(world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter, AVOID_WATER); + + for (Location spawn : spawnPoints) + { + addSpawnPoint(spawn); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/CannotGenerateSpawnPointsException.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/CannotGenerateSpawnPointsException.java new file mode 100644 index 0000000..b8289c8 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/CannotGenerateSpawnPointsException.java @@ -0,0 +1,43 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.spawns.exceptions; + + +public class CannotGenerateSpawnPointsException extends Exception +{ + + public CannotGenerateSpawnPointsException(String message) + { + super(message); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/UnknownGeneratorException.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/UnknownGeneratorException.java new file mode 100644 index 0000000..1ab5892 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/exceptions/UnknownGeneratorException.java @@ -0,0 +1,41 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spawns.exceptions; + +public class UnknownGeneratorException extends Exception +{ + + public UnknownGeneratorException(String message) + { + super(message); + } +} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/generators/CircularSpawnPointsGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/CircularSpawnPointsGenerator.java similarity index 50% rename from src/main/java/me/azenet/UHPlugin/spawns/generators/CircularSpawnPointsGenerator.java rename to src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/CircularSpawnPointsGenerator.java index 2662ce1..6fec2ee 100644 --- a/src/main/java/me/azenet/UHPlugin/spawns/generators/CircularSpawnPointsGenerator.java +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/CircularSpawnPointsGenerator.java @@ -1,45 +1,54 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) * - * 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. + * http://amaury.carrade.eu * - * 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. + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see [http://www.gnu.org/licenses/]. + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. */ -package me.azenet.UHPlugin.spawns.generators; +package eu.carrade.amaury.UHCReloaded.spawns.generators; -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import me.azenet.UHPlugin.utils.UHUtils; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import java.util.HashSet; import java.util.Random; import java.util.Set; -public class CircularSpawnPointsGenerator implements SpawnPointsGenerator { - - private UHPlugin p; - - public CircularSpawnPointsGenerator(UHPlugin p) { - this.p = p; - } - +public class CircularSpawnPointsGenerator implements SpawnPointsGenerator +{ + private final UHCReloaded p = UHCReloaded.get(); /** * Generates spawn points in concentric circles. @@ -59,18 +68,20 @@ public CircularSpawnPointsGenerator(UHPlugin p) { * @throws CannotGenerateSpawnPointsException In case of fail. */ @Override - public Set<Location> generate(World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter, boolean avoidWater) throws CannotGenerateSpawnPointsException { - + public Set<Location> generate(final World world, final int spawnCount, final int regionDiameter, final int minimalDistanceBetweenTwoPoints, final double xCenter, final double zCenter, final boolean avoidWater) throws CannotGenerateSpawnPointsException + { // We starts the generation on a smaller grid, to avoid false outside tests if the point is on the edge - int usedRegionDiameter = regionDiameter - 1; + final int usedRegionDiameter = regionDiameter - 1; int countGeneratedPoints = 0; - Set<Location> generatedPoints = new HashSet<Location>(); + final Set<Location> generatedPoints = new HashSet<>(); int currentCircleDiameter = usedRegionDiameter; // The generation loop. Each step generates a circle. - generationLoop: while(currentCircleDiameter >= minimalDistanceBetweenTwoPoints) { + generationLoop: + while (currentCircleDiameter >= minimalDistanceBetweenTwoPoints) + { // First step. We want to know if all the points left can be in one circle. // We calculates the maximal number of points in a circle, taking into account the // minimal distance between two points. @@ -80,26 +91,30 @@ public Set<Location> generate(World world, int spawnCount, int regionDiameter, i // a = 2 Arcsin((d/2)/R) // (Just draw the situation, you'll see.) - double denseCircleAngle = 2 * Math.asin(((double) minimalDistanceBetweenTwoPoints / 2) / ((double) currentCircleDiameter / 2)); - int pointsPerDenseCircles = (int) Math.floor(2 * Math.PI / denseCircleAngle); + final double denseCircleAngle = 2 * Math.asin(((double) minimalDistanceBetweenTwoPoints / 2) / ((double) currentCircleDiameter / 2)); + final int pointsPerDenseCircles = (int) Math.floor(2 * Math.PI / denseCircleAngle); - double angleBetweenTwoPoints; + final double angleBetweenTwoPoints; // Not all the points can be in this circle. We generate the densiest circle. - if(pointsPerDenseCircles < spawnCount - countGeneratedPoints) { + if (pointsPerDenseCircles < spawnCount - countGeneratedPoints) + { angleBetweenTwoPoints = 2 * Math.PI / ((double) pointsPerDenseCircles); } + // All the remaining points can be in this circle. We generates the less dense circle with // these points. - else { + else + { angleBetweenTwoPoints = 2 * Math.PI / ((double) (spawnCount - countGeneratedPoints)); } // Let's generate these points. - double startAngle = (new Random()).nextDouble() * 2 * Math.PI; + final double startAngle = (new Random()).nextDouble() * 2 * Math.PI; double currentAngle = startAngle; - circleLoop: while(currentAngle <= 2 * Math.PI - angleBetweenTwoPoints + startAngle) { + while (currentAngle <= 2 * Math.PI - angleBetweenTwoPoints + startAngle) + { // The coordinates of a point in the circle. // Cf. your trigonometry! ;) Location point = new Location( @@ -111,45 +126,53 @@ public Set<Location> generate(World world, int spawnCount, int regionDiameter, i currentAngle += angleBetweenTwoPoints; - if(!p.getBorderManager().isInsideBorder(point, regionDiameter)) { // Just in case - continue circleLoop; + // Just in case + if (!p.getBorderManager().isInsideBorder(point, regionDiameter)) + { + continue; } - Block surfaceBlock = world.getHighestBlockAt(point); + final Block surfaceAirBlock = world.getHighestBlockAt(point); + final Block surfaceBlock = surfaceAirBlock.getRelative(BlockFace.DOWN); // Safe spot available? - if(!UHUtils.isSafeSpot(surfaceBlock.getLocation())) { - continue circleLoop; // not safe: nope + if (!UHUtils.isSafeSpot(surfaceAirBlock.getLocation())) + { + continue; // not safe: nope } // Not above the water? - if(avoidWater) { - if(surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) { - continue circleLoop; + if (avoidWater) + { + if (surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) + { + continue; } } generatedPoints.add(point); countGeneratedPoints++; - if(countGeneratedPoints >= spawnCount) { + if (countGeneratedPoints >= spawnCount) + { break generationLoop; } } // So, this circle is done. // We prepares the next one. - currentCircleDiameter -= 2 *minimalDistanceBetweenTwoPoints; + currentCircleDiameter -= 2 * minimalDistanceBetweenTwoPoints; } // Generation done or failed (not enough space)? - if(generatedPoints.size() < spawnCount) { + if (generatedPoints.size() < spawnCount) + { // Failed! throw new CannotGenerateSpawnPointsException("Cannot generate the spawn point in circles: not enough space"); } - - else { + else + { return generatedPoints; } } diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/GridSpawnPointsGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/GridSpawnPointsGenerator.java new file mode 100644 index 0000000..4ab55ae --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/GridSpawnPointsGenerator.java @@ -0,0 +1,215 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spawns.generators; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.HashSet; +import java.util.Set; + + +public class GridSpawnPointsGenerator implements SpawnPointsGenerator +{ + private final UHCReloaded p = UHCReloaded.get(); + + /** + * Generates spawn points in a grid. + * + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will + * be generated.<br> This is limited by the size of the + * map. This will be seen as the diameter of a circular + * or of a squared map, following the shape of the world + * set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the + * region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the + * region where the points will be generated. + * @param avoidWater True if the generation have to avoid the water. + * + * @return The spawn points generated. + * @throws CannotGenerateSpawnPointsException In case of fail. + */ + @Override + public Set<Location> generate(final World world, final int spawnCount, final int regionDiameter, final int minimalDistanceBetweenTwoPoints, final double xCenter, final double zCenter, final boolean avoidWater) throws CannotGenerateSpawnPointsException + { + // We starts the generation on a smaller grid, to avoid false outside tests if the point is on the edge + final int usedRegionDiameter = regionDiameter - 1; + + // To check the possibility of the generation, we calculates the maximal number of columns/rows + // possible, based on the minimal distance between two points. + final int maxColumnsCount = (int) Math.ceil(usedRegionDiameter / minimalDistanceBetweenTwoPoints); + + // The points are on a grid + int neededColumnsCount = (int) Math.ceil(Math.sqrt(spawnCount)); + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + // If the border is circular, the distance between two points needs to be decreased. + // The space available is divided by PI/4, so the column count is multiplied by + // this number. + neededColumnsCount = (int) Math.ceil(neededColumnsCount / (Math.PI / 4)); + } + + // IS impossible. + if (neededColumnsCount > maxColumnsCount) + { + throw new CannotGenerateSpawnPointsException("Cannot generate spawn points on a grid: not enough space."); + } + + // If the map is circular, the generation may be impossible, because this check was + // performed for a squared map. + // The test will be done after the generation. + + + // We generates the points on a grid in squares, starting by the biggest square. + final int distanceBetweenTwoPoints = (int) ((double) usedRegionDiameter / ((double) (neededColumnsCount))); + + // Check related to the case the column count was increased. + if (distanceBetweenTwoPoints < minimalDistanceBetweenTwoPoints) + { + throw new CannotGenerateSpawnPointsException("Cannot generate spawn points on a grid: not enough space."); + } + + + int countGeneratedPoints = 0; + final HashSet<Location> generatedPoints = new HashSet<>(); + + final int halfDiameter = (int) Math.floor(usedRegionDiameter / 2); + + Integer currentSquareSize = usedRegionDiameter; + Location currentSquareStartPoint = new Location(world, xCenter + halfDiameter, 0, zCenter - halfDiameter); + Location currentPoint; + + // Represents the location to add on each side of the squares + final Location[] addOnSide = new Location[4]; + addOnSide[0] = new Location(world, -distanceBetweenTwoPoints, 0, 0); // North side, direction east + addOnSide[1] = new Location(world, 0, 0, distanceBetweenTwoPoints); // East side, direction south + addOnSide[2] = new Location(world, distanceBetweenTwoPoints, 0, 0); // South side, direction west + addOnSide[3] = new Location(world, 0, 0, -distanceBetweenTwoPoints); // West side, direction north + + // We generates the points until there isn't any point left to place. The loop will be broken. + // On each step of this loop, a square is generated. + generationLoop: + while (true) + { + currentPoint = currentSquareStartPoint.clone(); + + // First point + if (p.getBorderManager().isInsideBorder(currentPoint, regionDiameter) && UHUtils.searchSafeSpot(currentPoint) != null) + { + generatedPoints.add(currentPoint.clone()); + countGeneratedPoints++; + + if (countGeneratedPoints >= spawnCount) + { + break; + } + } + + // A step for each side, j is the side (see addOnSide). + for (int j = 0; j < 4; j++) + { + int plottedSize = 0; + + while (plottedSize < currentSquareSize) + { + currentPoint.add(addOnSide[j]); + plottedSize += distanceBetweenTwoPoints; + + // Inside the border? + if (!p.getBorderManager().isInsideBorder(currentPoint, regionDiameter)) + { + continue; + } + + final Block surfaceAirBlock = world.getHighestBlockAt(currentPoint); + final Block surfaceBlock = surfaceAirBlock.getRelative(BlockFace.DOWN); + + // Safe spot available? + if (!UHUtils.isSafeSpot(surfaceAirBlock.getLocation())) + { + continue; // not safe: nope + } + + // Not above the water? + if (avoidWater) + { + if (surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) + { + continue; + } + } + + generatedPoints.add(currentPoint.clone()); + countGeneratedPoints++; + + if (countGeneratedPoints >= spawnCount) + { + break generationLoop; + } + } + } + + // This square is complete; preparing the next one... + currentSquareSize -= 2 * distanceBetweenTwoPoints; + currentSquareStartPoint.add(new Location(world, -distanceBetweenTwoPoints, 0, distanceBetweenTwoPoints)); + + if (currentSquareSize < distanceBetweenTwoPoints) + { + // This may happens if we generates the points for a circular world + break; + } + } + + // If the generation was broken (circular world, not enough positions), + // the generation was incomplete. + if (countGeneratedPoints >= spawnCount) + { + // Generation OK + return generatedPoints; + } + else + { + throw new CannotGenerateSpawnPointsException("Cannot generate the spawn points: not enough space."); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/RandomSpawnPointsGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/RandomSpawnPointsGenerator.java new file mode 100644 index 0000000..1298997 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/RandomSpawnPointsGenerator.java @@ -0,0 +1,233 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.spawns.generators; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.HashSet; +import java.util.Random; +import java.util.Set; + + +/** + * Generates the spawn points randomly. + */ +public class RandomSpawnPointsGenerator implements SpawnPointsGenerator +{ + private final Random random = new Random(); + private final UHCReloaded p = UHCReloaded.get(); + + /** + * Generates randomly some spawn points in the map, with a minimal distance. + * + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> + * This is limited by the size of the map. This will be seen as the diameter of a circular or + * of a squared map, following the shape of the world set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. + * @param avoidWater True if the generation have to avoid the water. + * + * @return The spawn points generated. + * + * @throws CannotGenerateSpawnPointsException In case of fail + */ + @Override + public Set<Location> generate(final World world, final int spawnCount, final int regionDiameter, final int minimalDistanceBetweenTwoPoints, final double xCenter, final double zCenter, final boolean avoidWater) throws CannotGenerateSpawnPointsException + { + final double minimalDistanceBetweenTwoPointsSquared = Math.pow(minimalDistanceBetweenTwoPoints, 2); + + + /** Possible? **/ + + // If the surface of the map is too close of the sum of the surfaces of the private part + // around each spawn point (a circle with, as radius, the minimal distance between two spawn + // points), the generation will fail. + + final double surfacePrivatePartsAroundSpawnPoints = (int) (spawnCount * (Math.PI * minimalDistanceBetweenTwoPointsSquared)); + final double surfaceRegion; + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + surfaceRegion = (Math.PI * Math.pow(regionDiameter, 2)) / 4; + } + else + { + surfaceRegion = Math.pow(regionDiameter, 2); + } + + final double packingDensity = surfacePrivatePartsAroundSpawnPoints / surfaceRegion; + + // According to Lagrange and Thue's works on circle packagings, the highest density possible is + // approximately 0.9069 (with an hexagonal arrangement of the circles). + // Even with a packaging density very close to this limit, the generation time is correct. + // So we uses this as a limit. + if (packingDensity >= 0.9069) + { + throw new CannotGenerateSpawnPointsException("Unable to generate spawn points randomly: packing density too high"); + } + + /** Generation **/ + + final Set<Location> randomSpawnPoints = new HashSet<>(); + int generatedSpawnPoints = 0; + + // If the first points are badly located, and if the density is high, the generation may + // be impossible to end. + // So, after 15 generation fails of a point due to this point being placed too close + // of other ones, we restarts all the generation. + int currentErrorCount = 0; + + // With the "avoid above water" option, if there's a lot of water, the genaration may + // fail even if the surface seems to be ok to host the requested spawn points. + // So, after 2*{points requested} points above the water, we cancels the generation. + int pointsAboveWater = 0; + + generationLoop: + while (generatedSpawnPoints != spawnCount) + { + // "Too many fails" test + if (currentErrorCount >= 16) // restart + { + randomSpawnPoints.clear(); + generatedSpawnPoints = 0; + currentErrorCount = 0; + } + + // "Too many points above the water" test + if (pointsAboveWater >= 2 * spawnCount) + { + throw new CannotGenerateSpawnPointsException("Too many spawn points above the water."); + } + + + // We generates a point in the square of side regionDiameter. + // In case of a circular world, if the point was generated out of the circle, it will be + // excluded when his presence inside the region will be checked. + + Location randomPoint = new Location(world, + random((int) (xCenter - Math.floor(regionDiameter / 2)), (int) (xCenter + (int) Math.floor(regionDiameter / 2))), + 0, + random((int) (zCenter - Math.floor(regionDiameter / 2)), (int) (zCenter + (int) Math.floor(regionDiameter / 2)))); + + // Inside the region? + if (!p.getBorderManager().isInsideBorder(randomPoint, regionDiameter)) + { + continue; // outside: nope + } + + final Block surfaceAirBlock = world.getHighestBlockAt(randomPoint); + final Block surfaceBlock = surfaceAirBlock.getRelative(BlockFace.DOWN); + + // Safe spot available? + if (!UHUtils.isSafeSpot(surfaceAirBlock.getLocation())) + { + continue; // not safe: nope + } + + // Not above the water? + if (avoidWater) + { + if (surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) + { + pointsAboveWater++; + continue; + } + } + + // Is that point at a correct distance of the other ones? + for (Location spawn : randomSpawnPoints) + { + if (spawn.distanceSquared(randomPoint) < minimalDistanceBetweenTwoPointsSquared) + { + currentErrorCount++; + continue generationLoop; // too close: nope + } + } + + // Well, all done. + randomSpawnPoints.add(randomPoint); + generatedSpawnPoints++; + currentErrorCount = 0; + } + + // Generation done, let's register these points. + + return randomSpawnPoints; + } + + + /** + * Generates a random number between min and max. + * + * @param min The minimum value. May be negative. Inclusive. + * @param max The maximum value. May be negative. Inclusive. + * @return A random number between these two points. + */ + public Integer random(int min, int max) + { + if (min == max) + { + return min; + } + + if (min > max) // swap + { + min = min + max; + max = min - max; + min = min - max; + } + + if (min >= 0 && max >= 0) + { + return random.nextInt(max - min + 1) + min; + } + else if (min <= 0 && max <= 0) + { + return -1 * (random.nextInt(Math.abs(min - max)) + Math.abs(max)); + } + else // min <= 0 && max >= 0 + { + return random.nextInt(Math.abs(min) + Math.abs(max)) - Math.abs(min); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/SpawnPointsGenerator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/SpawnPointsGenerator.java new file mode 100644 index 0000000..3342a25 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spawns/generators/SpawnPointsGenerator.java @@ -0,0 +1,68 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spawns.generators; + +import eu.carrade.amaury.UHCReloaded.spawns.exceptions.CannotGenerateSpawnPointsException; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Set; + + +/** + * Represents a spawn points generator. + * + * <p> + * A zero-arguments constructor is needed. + * </p> + */ +public interface SpawnPointsGenerator +{ + /** + * Generates the spawn points. + * + * @param world The world where the spawn points will be generated. + * @param spawnCount The number of spawn points to generate. + * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> + * This is limited by the size of the map. This will be seen as the diameter of a circular or + * of a squared map, following the shape of the world set in the configuration. + * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. + * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. + * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. + * @param avoidWater True if the generation have to avoid the water. + * + * @return The spawn points generated. + * + * @throws CannotGenerateSpawnPointsException In case of fail. + */ + Set<Location> generate(final World world, final int spawnCount, final int regionDiameter, final int minimalDistanceBetweenTwoPoints, final double xCenter, final double zCenter, final boolean avoidWater) throws CannotGenerateSpawnPointsException; +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SPlusSpectatorsManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SPlusSpectatorsManager.java new file mode 100644 index 0000000..7ab6344 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SPlusSpectatorsManager.java @@ -0,0 +1,62 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spectators; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import org.bukkit.entity.Player; + + +/** + * Spectators managed through the SpectatorsPlus Bukkit plugin by PGMann and AmauryPi. + */ +public class SPlusSpectatorsManager extends SpectatorsManager +{ + UHCReloaded p; + + public SPlusSpectatorsManager() + { + p = UHCReloaded.get(); + } + + @Override + public void setSpectating(final Player player, final boolean spectating) + { + if (player != null && p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) + p.getSpectatorPlusIntegration().getSPAPI().setSpectating(player, spectating); + } + + @Override + public boolean isSpectating(Player player) + { + return player != null && p.getSpectatorPlusIntegration().isSPIntegrationEnabled() && p.getSpectatorPlusIntegration().getSPAPI().isSpectator(player); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SpectatorsManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SpectatorsManager.java new file mode 100644 index 0000000..8acba07 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/SpectatorsManager.java @@ -0,0 +1,98 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spectators; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.UUID; + + +/** + * Represents a spectator manager, able to put players in or remove players from spectator mode. + */ +public abstract class SpectatorsManager +{ + /** + * Changes the spectating mode of a player. + * + * @param player The player. + * @param spectating {@code true} to enable the spectator mode; {@code false} to disable it. + */ + public abstract void setSpectating(final Player player, final boolean spectating); + + /** + * Checks if the given player is currently spectating. + * + * @param player The player. + * + * @return {@code true} if spectating. + */ + public abstract boolean isSpectating(final Player player); + + /** + * Changes the spectating mode of a player. + * + * @param playerID The player's UUID. + * @param spectating {@code true} to enable the spectator mode; {@code false} to disable it. + */ + public void setSpectating(final UUID playerID, final boolean spectating) + { + setSpectating(Bukkit.getPlayer(playerID), spectating); + } + + /** + * Checks if the given player is currently spectating. + * + * @param playerID The player's UUID. + * + * @return {@code true} if spectating. + */ + public boolean isSpectating(final UUID playerID) + { + return isSpectating(Bukkit.getPlayer(playerID)); + } + + + /** + * @return an instance of a {@link SpectatorsManager}: {@link SPlusSpectatorsManager} if the + * SpectatorPlus plugin is available; {@link VanillaSpectatorsManager} else. + */ + public static SpectatorsManager getInstance() + { + if (UHCReloaded.get().getSpectatorPlusIntegration().isSPIntegrationEnabled()) + return new SPlusSpectatorsManager(); + else + return new VanillaSpectatorsManager(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/VanillaSpectatorsManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/VanillaSpectatorsManager.java new file mode 100644 index 0000000..81d175c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/spectators/VanillaSpectatorsManager.java @@ -0,0 +1,83 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.spectators; + + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + + +/** + * Vanilla spectator mode + */ +public class VanillaSpectatorsManager extends SpectatorsManager +{ + /** + * Stores the previous gamemodes of the players. + */ + private Map<UUID, GameMode> oldGameModes = new HashMap<>(); + + + @Override + public void setSpectating(final Player player, final boolean spectating) + { + if (player == null) + return; + + if (spectating) + { + if (player.getGameMode() != GameMode.SPECTATOR) + { + oldGameModes.put(player.getUniqueId(), player.getGameMode()); + player.setGameMode(GameMode.SPECTATOR); + } + } + else + { + GameMode previousMode = oldGameModes.get(player.getUniqueId()); + player.setGameMode(previousMode != null ? previousMode : Bukkit.getDefaultGameMode()); + + oldGameModes.remove(player.getUniqueId()); + } + } + + @Override + public boolean isSpectating(Player player) + { + return player != null && player.getGameMode() == GameMode.SPECTATOR; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java b/src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java new file mode 100644 index 0000000..1284809 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java @@ -0,0 +1,75 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.task; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.borders.MapShape; +import fr.zcraft.zlib.components.i18n.I; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + + +public class BorderWarningTask extends BukkitRunnable +{ + private UHCReloaded p = null; + + public BorderWarningTask(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run() + { + if (p.getFreezer().getGlobalFreezeState()) + { + return; // No messages are sent if the game is frozen. + } + + // Message sent to all players outside the border + for (Player player : p.getBorderManager().getPlayersOutside(p.getBorderManager().getWarningSize())) + { + double distance = p.getBorderManager().getDistanceToBorder(player.getLocation(), p.getBorderManager().getWarningSize()); + + if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) + { + player.sendMessage(I.tn("{ce}You are currently out of the future border (diameter of {0} block).", "{ce}You are currently out of the future border (diameter of {0} blocks).", p.getBorderManager().getWarningSize())); + } + else + { + player.sendMessage(I.t("{ce}You are currently out of the future border of {0}×{0} blocks.", p.getBorderManager().getWarningSize())); + } + + player.sendMessage(I.tn("{ci}You have {0} block to go before being inside.", "{ci}You have {0} blocks to go before being inside.", (int) distance)); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/task/CancelBrewTask.java b/src/main/java/eu/carrade/amaury/UHCReloaded/task/CancelBrewTask.java new file mode 100644 index 0000000..92ae66e --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/task/CancelBrewTask.java @@ -0,0 +1,109 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.task; + +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.BrewerInventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + + +public class CancelBrewTask extends BukkitRunnable +{ + private BrewerInventory inventory = null; + private HumanEntity whoClicked = null; + + public CancelBrewTask(BrewerInventory inventory, HumanEntity whoClicked) + { + this.inventory = inventory; + this.whoClicked = whoClicked; + } + + @Override + public void run() + { + if (inventory.getIngredient() == null) + { + return; // Nothing to do! + } + + if (whoClicked instanceof Player) + { + ItemStack ingredient = inventory.getIngredient(); + + if (ingredient.getType() != null && ingredient.getType().equals(Material.GLOWSTONE_DUST)) + { + inventory.setIngredient(new ItemStack(Material.AIR)); // The glowstone is removed. + + // First try: try to add the glowstone to an existing stack + Boolean added = false; + for (ItemStack item : whoClicked.getInventory().getContents()) + { + if (item != null && item.getType() != null && item.getType().equals(Material.GLOWSTONE_DUST)) + { + if (item.getAmount() + ingredient.getAmount() <= item.getMaxStackSize()) + { + // We can add the glowstone here. + item.setAmount(item.getAmount() + ingredient.getAmount()); + added = true; + break; + } + } + } + + // Failed... We adds the glowstone to the first empty slot found. + if (!added) + { + Integer slotEmpty = whoClicked.getInventory().firstEmpty(); + + // -1 is returned if there isn't any empty slot + if (slotEmpty != -1) + { + whoClicked.getInventory().setItem(slotEmpty, ingredient); + } + + // Failed again (!). Maybe an item captured between the click and this execution. + // The stack is dropped at the player's location. + else + { + whoClicked.getWorld().dropItem(whoClicked.getLocation(), ingredient); + } + } + + ((Player) whoClicked).updateInventory(); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/task/FireworksOnWinnersTask.java b/src/main/java/eu/carrade/amaury/UHCReloaded/task/FireworksOnWinnersTask.java new file mode 100644 index 0000000..09d1c5a --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/task/FireworksOnWinnersTask.java @@ -0,0 +1,92 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.task; + +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.utils.UHUtils; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Random; +import java.util.Set; + + +public class FireworksOnWinnersTask extends BukkitRunnable +{ + private Set<OfflinePlayer> winners = null; + + private Double areaSize; + private Random rand; + + private long startTime = 0L; + + public FireworksOnWinnersTask(Set<OfflinePlayer> listWinners) + { + this.winners = listWinners; + + this.areaSize = UHConfig.FINISH.FIREWORKS.AREA_SIZE.get(); + this.rand = new Random(); + + this.startTime = System.currentTimeMillis(); + } + + @Override + public void run() + { + // The fireworks are launched in a square centered on the player. + Double halfAreaSize = areaSize / 2; + + for (OfflinePlayer winner : winners) + { + if (winner.isOnline()) + { + Location fireworkLocation = ((Player) winner).getLocation(); + + fireworkLocation.add(rand.nextDouble() * areaSize - halfAreaSize, // a number between -halfAreaSize and halfAreaSize + 2, // y+2 for a clean vision of the winner. + rand.nextDouble() * areaSize - halfAreaSize); + + UHUtils.generateRandomFirework(fireworkLocation, 0, 15); + UHUtils.generateRandomFirework(fireworkLocation.add(0.2, 0d, 0.2), 0, 15); + UHUtils.generateRandomFirework(fireworkLocation.add(-0.2, 0d, 0.2), 0, 15); + } + } + + if ((System.currentTimeMillis() - startTime) / 1000 > UHConfig.FINISH.FIREWORKS.DURATION.get()) + { + this.cancel(); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/task/ScheduledCommandsExecutorTask.java b/src/main/java/eu/carrade/amaury/UHCReloaded/task/ScheduledCommandsExecutorTask.java new file mode 100644 index 0000000..838abf5 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/task/ScheduledCommandsExecutorTask.java @@ -0,0 +1,71 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.task; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.command.CommandException; + +import java.util.HashSet; + + +/** + * Schedules a stack of commands executed at the same time. + */ +public class ScheduledCommandsExecutorTask implements Runnable +{ + private UHCReloaded p = null; + private HashSet<String> commands = null; + + public ScheduledCommandsExecutorTask(UHCReloaded plugin, HashSet<String> commands) + { + this.p = plugin; + this.commands = commands; + } + + @Override + public void run() + { + for (String command : commands) + { + try + { + p.getServer().dispatchCommand(p.getServer().getConsoleSender(), command); + } + catch (CommandException e) + { + PluginLogger.error("The scheduled command '{0}' failed.", e, command); + } + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/task/UpdateTimerTask.java b/src/main/java/eu/carrade/amaury/UHCReloaded/task/UpdateTimerTask.java new file mode 100644 index 0000000..c89ce71 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/task/UpdateTimerTask.java @@ -0,0 +1,56 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.task; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.timers.UHTimer; +import org.bukkit.scheduler.BukkitRunnable; + + +public class UpdateTimerTask extends BukkitRunnable +{ + private UHCReloaded p = null; + + public UpdateTimerTask(UHCReloaded p) + { + this.p = p; + } + + @Override + public void run() + { + for (UHTimer timer : p.getTimerManager().getRunningTimers()) + { + timer.update(); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java new file mode 100644 index 0000000..e904cbe --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java @@ -0,0 +1,358 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.teams; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.protips.ProTips; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.runners.RunTask; +import fr.zcraft.zlib.tools.text.MessageSender; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + + +public class TeamChatManager +{ + private final UHCReloaded p; + + private final Set<UUID> teamChatLocked = new HashSet<>(); + private final Map<UUID, UHTeam> otherTeamChatLocked = new HashMap<>(); + private final Set<UUID> globalSpies = new HashSet<>(); + + public TeamChatManager(UHCReloaded p) + { + this.p = p; + } + + /** + * Sends a team-message from the given sender. + * + * @param sender The sender. + * @param message The message to send. + */ + public void sendTeamMessage(Player sender, String message) + { + sendTeamMessage(sender, message, null); + } + + /** + * Sends a team-message from the given sender. + * + * @param sender The sender. + * @param message The message to send. + * @param team If not null, this message will be considered as an external message from another player to this team. + */ + public void sendTeamMessage(Player sender, String message, UHTeam team) + { + // Permission check + if (team == null && !sender.hasPermission("uh.teamchat.self")) + { + sender.sendMessage(I.t("{ce}You are not allowed to send a private message to your team.")); + return; + } + if (team != null && !sender.hasPermission("uh.teamchat.others")) + { + sender.sendMessage(I.t("{ce}You are not allowed to enter in the private chat of another team.")); + return; + } + + String rawMessage; + UHTeam recipient; + + if (team == null) + { + /// Format of a private team message from a team member. {0} = sender display name, {1} = message. + rawMessage = I.t("{gold}[{0}{gold} -> his team] {reset}{1}", sender.getDisplayName(), message); + recipient = p.getTeamManager().getTeamForPlayer(sender); + + if (recipient == null) + { + /// Error message if someone try to send a team private message out of any team + sender.sendMessage(I.t("{ce}You are not in a team!")); + return; + } + } + else + { + /// Format of a private team message from a non-team-member. {0} = sender display name, {1} = team display name, {2} = message. + rawMessage = I.t("{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}", sender.getDisplayName(), team.getDisplayName(), message); + recipient = team; + } + + sendRawTeamMessage(sender, rawMessage, recipient); + } + + /** + * Sends a raw team-message from the given player. + * + * @param sender The sender of this message. + * @param rawMessage The raw message to be sent. + * @param team The recipient of this message. + */ + private void sendRawTeamMessage(final Player sender, String rawMessage, UHTeam team) + { + // The message is sent to the players of the team... + for (final Player player : team.getOnlinePlayers()) + { + MessageSender.sendChatMessage(player, rawMessage); + } + + // ... to the spies ... + if (otherTeamChatLocked.containsValue(team)) + { + for (UUID playerId : otherTeamChatLocked.keySet()) + { + // The message is only sent to the spies not in the team, to avoid double messages + if (otherTeamChatLocked.get(playerId).equals(team) && !team.containsPlayer(playerId)) + { + MessageSender.sendChatMessage(p.getServer().getPlayer(playerId), rawMessage); + } + } + } + + // ... to the global spies ... + for (UUID playerId : globalSpies) + { + if (!team.containsPlayer(playerId)) + { + p.getServer().getPlayer(playerId).sendMessage(rawMessage); + } + } + + // ... and to the console. + if (UHConfig.TEAMS_OPTIONS.TEAM_CHAT.LOG.get()) + { + p.getServer().getConsoleSender().sendMessage(rawMessage); + } + + RunTask.later(new Runnable() + { + @Override + public void run() + { + ProTips.LOCK_CHAT.sendTo(sender); + } + }, 30L); + } + + /** + * Sends a global message from the given player. + * + * @param sender The sender of this message. + * @param message The message to be sent. + */ + public void sendGlobalMessage(Player sender, String message) + { + // This message will be sent synchronously. + // The players' messages are sent asynchronously. + // That's how we differentiates the messages sent through /g and the messages sent using + // the normal chat. + sender.chat(message); + } + + + /** + * Toggles the chat between the global chat and the team chat. + * + * @param player The chat of this player will be toggled. + * @return {@code true} if the chat is now the team chat; false else. + */ + public boolean toggleChatForPlayer(Player player) + { + return toggleChatForPlayer(player, null); + } + + /** + * Toggles the chat between the global chat and the team chat. + * + * @param player The chat of this player will be toggled. + * @param team The team to chat with. If null, the player's team will be used. + * @return {@code true} if the chat is now the team chat; false else. + */ + public boolean toggleChatForPlayer(final Player player, UHTeam team) + { + // Permission check + if (team == null && !player.hasPermission("uh.teamchat.self")) + { + player.sendMessage(I.t("{ce}You are not allowed to send a private message to your team.")); + return false; + } + if (team != null && !player.hasPermission("uh.teamchat.others")) + { + player.sendMessage(I.t("{ce}You are not allowed to enter in the private chat of another team.")); + return false; + } + + + // If the team is not null, we will always go to the team chat + // Else, normal toggle + + if (team != null) + { + // if the player was in another team chat before, we removes it. + teamChatLocked.remove(player.getUniqueId()); + otherTeamChatLocked.put(player.getUniqueId(), team); + + return true; + } + + else + { + if (isAnyTeamChatEnabled(player)) + { + teamChatLocked.remove(player.getUniqueId()); + otherTeamChatLocked.remove(player.getUniqueId()); + + return false; + } + else + { + teamChatLocked.add(player.getUniqueId()); + + RunTask.later(new Runnable() + { + @Override + public void run() + { + ProTips.USE_G_COMMAND.sendTo(player); + } + }, 10L); + + return true; + } + } + } + + /** + * Returns true if the team chat is enabled for the given player. + * + * @param player The player. + * @param team If non-null, this will check if the given player is spying the current team. + * @return {@code true} if the team chat is enabled for the given player. + */ + public boolean isTeamChatEnabled(Player player, UHTeam team) + { + if (team == null) + { + return teamChatLocked.contains(player.getUniqueId()); + } + else + { + UHTeam lockedTeam = this.otherTeamChatLocked.get(player.getUniqueId()); + UHTeam playerTeam = p.getTeamManager().getTeamForPlayer(player); + return (lockedTeam != null && lockedTeam.equals(team)) || (playerTeam != null && playerTeam.equals(team)); + } + } + + /** + * Returns true if the team chat is enabled for the given player. + * + * @param player The player. + * @return {@code true} if the team chat is enabled for the given player. + */ + public boolean isTeamChatEnabled(Player player) + { + return this.isTeamChatEnabled(player, null); + } + + /** + * Returns true if the given player is in the team chat of another team. + * + * @param player The player. + * @return {@code true} if the given player is in the team chat of another team. + */ + public boolean isOtherTeamChatEnabled(Player player) + { + return otherTeamChatLocked.containsKey(player.getUniqueId()); + } + + /** + * Returns true if a team chat is enabled for the given player. + * + * @param player The player. + * @return {@code true} if a team chat is enabled for the given player. + */ + public boolean isAnyTeamChatEnabled(Player player) + { + return (teamChatLocked.contains(player.getUniqueId()) || otherTeamChatLocked.containsKey(player.getUniqueId())); + } + + /** + * Returns the other team viewed by the given player, or null if the player is not in + * the chat of another team. + * + * @param player The player. + * @return The other team viewed by the given player. + */ + public UHTeam getOtherTeamEnabled(Player player) + { + return otherTeamChatLocked.get(player.getUniqueId()); + } + + + /** + * Registers a player receiving ALL the teams chats. + * + * @param id The spy's UUID. + */ + public void addGlobalSpy(UUID id) + { + globalSpies.add(id); + } + + /** + * Stops a player from receiving ALL the teams chats. + * + * @param id The spy's UUID. + */ + public void removeGlobalSpy(UUID id) + { + globalSpies.remove(id); + } + + /** + * Checks if the given player receives all the teams chats. + * + * @param id The spy's UUID. + * @return {@code true} if spying. + */ + public boolean isGlobalSpy(UUID id) + { + return globalSpies.contains(id); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamColor.java b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamColor.java new file mode 100644 index 0000000..558b58f --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamColor.java @@ -0,0 +1,145 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.teams; + +import org.bukkit.ChatColor; + +import java.util.HashMap; +import java.util.Map; + + +/** + * Represents a team color. + * + * Also used to convert a string to a ChatColor object. + */ +public enum TeamColor +{ + AQUA("Aqua", ChatColor.AQUA), + BLACK("Black", ChatColor.BLACK), + BLUE("Blue", ChatColor.BLUE), + DARK_AQUA("Darkaqua", ChatColor.DARK_AQUA), + DARK_BLUE("Darkblue", ChatColor.DARK_BLUE), + DARK_GRAY("Darkgray", ChatColor.DARK_GRAY), + DARK_GREEN("Darkgreen", ChatColor.DARK_GREEN), + DARK_PURPLE("Darkpurple", ChatColor.DARK_PURPLE), + DARK_RED("Darkred", ChatColor.DARK_RED), + GOLD("Gold", ChatColor.GOLD), + GRAY("Gray", ChatColor.GRAY), + GREEN("Green", ChatColor.GREEN), + LIGHT_PURPLE("Lightpurple", ChatColor.LIGHT_PURPLE), + RED("Red", ChatColor.RED), + WHITE("White", ChatColor.WHITE), + YELLOW("Yellow", ChatColor.YELLOW), + RANDOM("?", null); + + + private static Map<ChatColor, TeamColor> BY_CHAT_COLOR = new HashMap<>(); + + static + { + for (TeamColor color : values()) + if (color.toChatColor() != null) + BY_CHAT_COLOR.put(color.toChatColor(), color); + } + + + private String name; + private ChatColor color; + + TeamColor(String name, ChatColor color) + { + this.name = name; + this.color = color; + } + + public ChatColor toChatColor() + { + return this.color; + } + + /** + * Returns a ChatColor object from a string. + * + * @param name The name of the color. + * @return The ChatColor object (null if RANDOM or not found). + */ + public static ChatColor getChatColorByName(String name) + { + for (TeamColor color : values()) + { + if (color.name.equalsIgnoreCase(name)) return color.color; + } + + return null; + } + + /** + * Case&trim-insensitive version of {@link #valueOf(String)}. + * + * @param name The name to get. + * @return A TeamColor value, or null if no value found. + */ + public static TeamColor fromString(String name) + { + if (name.equals("?")) + { + return RANDOM; + } + + try + { + return valueOf(name.trim().toUpperCase()); + } + catch (IllegalArgumentException e) + { + // Maybe a color without underscore + for (TeamColor color : values()) + { + if (color.name.equalsIgnoreCase(name)) return color; + } + + return null; + } + } + + /** + * Returns the TeamColor enum member associated to the given ChatColor. + * + * @param color The ChatColor. + * @return The corresponding TeamColor. + */ + public static TeamColor fromChatColor(ChatColor color) + { + return BY_CHAT_COLOR.get(color); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java new file mode 100644 index 0000000..46c3bcf --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java @@ -0,0 +1,684 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.teams; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.gui.teams.TeamsSelectorGUI; +import eu.carrade.amaury.UHCReloaded.gui.teams.editor.TeamEditDeleteGUI; +import eu.carrade.amaury.UHCReloaded.gui.teams.editor.TeamEditGUI; +import eu.carrade.amaury.UHCReloaded.gui.teams.editor.TeamEditMembersGUI; +import fr.zcraft.zlib.components.configuration.ConfigurationParseException; +import fr.zcraft.zlib.components.configuration.ConfigurationValueHandler; +import fr.zcraft.zlib.components.configuration.ConfigurationValueHandlers; +import static fr.zcraft.zlib.components.configuration.ConfigurationValueHandlers.getListValue; +import static fr.zcraft.zlib.components.configuration.ConfigurationValueHandlers.getValue; +import fr.zcraft.zlib.components.gui.Gui; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.rawtext.RawText; +import fr.zcraft.zlib.tools.PluginLogger; +import fr.zcraft.zlib.tools.text.ActionBar; +import fr.zcraft.zlib.tools.text.RawMessage; +import java.util.ArrayList; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; +import org.bukkit.DyeColor; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.material.Banner; + + +public class TeamManager +{ + private final int MAX_PLAYERS_PER_TEAM; + + private final UHCReloaded p; + private final HashSet<UHTeam> teams = new HashSet<>(); + + + public TeamManager(UHCReloaded plugin) + { + p = plugin; + + MAX_PLAYERS_PER_TEAM = UHConfig.TEAMS_OPTIONS.MAX_PLAYERS_PER_TEAM.get(); + } + + /** + * Is the given team registered? + * + * @param team The team. + * @return {@code true} if the team is registered. + */ + public boolean isTeamRegistered(UHTeam team) + { + return teams.contains(team); + } + + /** + * Is the given team registered? + * + * @param name The name of the team. + * @return {@code true} if the team is registered. + */ + public boolean isTeamRegistered(String name) + { + return getTeam(name) != null; + } + + + /** + * Adds a team. + * + * @param color The color. + * @param name The name of the team. + * + * @return The new team. + * + * @throws IllegalArgumentException if a team with the same name already exists. + */ + public UHTeam addTeam(TeamColor color, String name) + { + if (isTeamRegistered(name)) + { + throw new IllegalArgumentException("There is already a team named " + name + " registered!"); + } + + UHTeam team = new UHTeam(name, generateColor(color)); + teams.add(team); + + updateGUIs(); + + return team; + } + + /** + * Adds a team. A name is generated based on the color. + * + * @param color The color. + * + * @return The new team. + * + * @throws IllegalArgumentException if a team with the same name already exists. + */ + public UHTeam addTeam(TeamColor color) + { + + color = generateColor(color); + String teamName = color.toString().toLowerCase(); + + if (isTeamRegistered(teamName)) // Taken! + { + Random rand = new Random(); + do + { + teamName = color.toString().toLowerCase() + rand.nextInt(1000); + } while (isTeamRegistered(teamName)); + } + + UHTeam team = new UHTeam(teamName, color); + teams.add(team); + + updateGUIs(); + + return team; + } + + /** + * Adds a team from an UHTeam object. + * + * @param team The team. + * @return The new team. + * + * @throws IllegalArgumentException if a team with the same name already exists. + */ + public UHTeam addTeam(UHTeam team) + { + if (isTeamRegistered(team)) + { + throw new IllegalArgumentException("There is already a team named " + team.getName() + " registered!"); + } + + teams.add(team); + + updateGUIs(); + + return team; + } + + /** + * Deletes a team. + * + * @param team The team to delete. + * @param dontNotify If true, the player will not be notified about the leave. + * @return boolean True if a team was removed. + */ + public boolean removeTeam(UHTeam team, boolean dontNotify) + { + if (team != null) + { + if (dontNotify) + { + for (OfflinePlayer player : team.getPlayers()) + { + this.removePlayerFromTeam(player, true); + } + } + + team.deleteTeam(); + } + + final boolean removed = teams.remove(team); + + updateGUIs(); + + return removed; + } + + /** + * Deletes a team. + * + * @param team The team to delete. + * @return boolean True if a team was removed. + */ + public boolean removeTeam(UHTeam team) + { + return removeTeam(team, false); + } + + /** + * Deletes a team. + * + * @param name The name of the team to delete. + * @return boolean True if a team was removed. + */ + public boolean removeTeam(String name) + { + return removeTeam(getTeam(name), false); + } + + /** + * Deletes a team. + * + * @param name The name of the team to delete. + * @param dontNotify If true, the player will not be notified about the leave. + * @return boolean True if a team was removed. + */ + public boolean removeTeam(String name, boolean dontNotify) + { + return removeTeam(getTeam(name), dontNotify); + } + + /** + * Adds a player to a team. + * + * @param teamName The team in which we adds the player. + * @param player The player to add. + * @throws IllegalArgumentException if the team does not exists. + */ + public void addPlayerToTeam(String teamName, OfflinePlayer player) + { + UHTeam team = getTeam(teamName); + + if (team == null) + { + throw new IllegalArgumentException("There isn't any team named" + teamName + " registered!"); + } + + team.addPlayer(player); + } + + /** + * Removes a player from his team. + * + * @param player The player to remove. + * @param dontNotify If true, the player will not be notified about the leave. + */ + public void removePlayerFromTeam(OfflinePlayer player, boolean dontNotify) + { + UHTeam team = getTeamForPlayer(player); + if (team != null) + { + team.removePlayer(player, dontNotify); + } + } + + /** + * Removes a player from his team. + * + * @param player The player to remove. + */ + public void removePlayerFromTeam(OfflinePlayer player) + { + removePlayerFromTeam(player, false); + } + + + /** + * Removes all teams. + * + * @param dontNotify If true, the player will not be notified when they leave the destroyed team. + */ + public void reset(boolean dontNotify) + { + // 1: scoreboard reset + for (UHTeam team : new HashSet<>(teams)) + { + this.removeTeam(team, dontNotify); + } + + // 2: internal list reset + teams.clear(); + + updateGUIs(); + } + + /** + * Removes all teams. + */ + public void reset() + { + reset(false); + } + + /** + * Sets the correct display name of a player, according to his team. + * + * @param offlinePlayer The player to colorize. + */ + public void colorizePlayer(OfflinePlayer offlinePlayer) + { + if (!UHConfig.COLORIZE_CHAT.get()) + { + return; + } + + if (!offlinePlayer.isOnline()) + { + return; + } + + Player player = (Player) offlinePlayer; + + UHTeam team = getTeamForPlayer(player); + + if (team == null) + { + player.setDisplayName(player.getName()); + } + else + { + if (team.getColor() != null) + { + player.setDisplayName(team.getColor().toChatColor() + player.getName() + ChatColor.RESET); + } + else + { + player.setDisplayName(player.getName()); + } + } + } + + /** + * Returns all the teams. + * + * @return The teams. + */ + public Set<UHTeam> getTeams() + { + return teams; + } + + /** + * Returns the maximal number of players in each team. + * + * @return The max. + */ + public int getMaxPlayersPerTeam() + { + return MAX_PLAYERS_PER_TEAM; + } + + /** + * Returns the UHTeam object of the team with the given name. + * + * @param name The name of the team. + * @return The team, or null if the team does not exists. + */ + public UHTeam getTeam(String name) + { + for (UHTeam t : teams) + { + if (t.getName().equalsIgnoreCase(name)) + { + return t; + } + } + + return null; + } + + /** + * Gets a player's team. + * + * @param player The player. + * @return The team of this player. + */ + public UHTeam getTeamForPlayer(OfflinePlayer player) + { + for (UHTeam t : teams) + { + if (t.containsPlayer(player.getUniqueId())) return t; + } + + return null; + } + + /** + * Checks if two players are in the same team. + * + * @param player1 The first player. + * @param player2 The second player + * @return True if the players are in the same team, false else. + */ + public boolean inSameTeam(Player player1, Player player2) + { + return (getTeamForPlayer(player1).equals(getTeamForPlayer(player2))); + } + + /** + * Generates a color from the given color. + * <p> + * If the color is neither {@link TeamColor#RANDOM} nor {@code null}, returns the given color.<br /> + * Else, generates a random unused (if possible) color. + * @param color + * @return + */ + public TeamColor generateColor(TeamColor color) + { + if (color != null && color != TeamColor.RANDOM) + { + return color; + } + + // A list of the currently used colors. + HashSet<TeamColor> availableColors = new HashSet<TeamColor>(Arrays.asList(TeamColor.values())); + availableColors.remove(TeamColor.RANDOM); + for (UHTeam team : getTeams()) + { + availableColors.remove(team.getColor()); + } + + if (availableColors.size() != 0) + { + return (TeamColor) availableColors.toArray()[(new Random()).nextInt(availableColors.size())]; + } + else + { + // length-1 so the RANDOM option is never selected. + return TeamColor.values()[(new Random()).nextInt(TeamColor.values().length - 1)]; + } + } + + /** + * Imports the teams from the configuration. + * + * @return The number of teams imported. + */ + public int importTeamsFromConfig() + { + int teamsCount = 0; + for (String teamDescription : UHConfig.TEAMS) + { + try + { //TODO: Sanitize UHTeam to allow it being loaded directly by the configuration. + addTeam(handleTeamValue(teamDescription)); + } + catch (ConfigurationParseException ex) + { + PluginLogger.warning("Invalid team value : ''{0}''.", ex.getValue()); + PluginLogger.warning("\tReason : {0}", ex.getMessage()); + } + } + + for(Entry<String, BannerMeta> bannerEntry : UHConfig.TEAM_BANNERS) + { + UHTeam team = getTeam(bannerEntry.getKey()); + if(team == null) continue; + team.setBanner(bannerEntry.getValue()); + } + + return teamsCount; + } + + /** + * Displays a chat-based GUI (using tellraw formatting) to player to select a team. + * <p> + * Nothing is displayed if the player cannot use the /join command. + * + * @param player The receiver of the chat-GUI. + */ + public void displayTeamChooserChatGUI(Player player) + { + if (!player.hasPermission("uh.player.join.self")) return; + + if (p.getGameManager().isGameRunning()) + { + if (!p.getGameManager().isGameWithTeams()) + { + return; + } + } + + player.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); + + if (p.getTeamManager().getTeams().size() != 0) + { + /// Invite displayed in the chat team selector + player.sendMessage(I.t("{gold}Click on the names below to join a team")); + + boolean displayPlayers = UHConfig.TEAMS_OPTIONS.GUI.DISPLAY_PLAYERS_IN_TEAMS.get(); + + for (UHTeam team : p.getTeamManager().getTeams()) + { + String players = ""; + if (displayPlayers) + { + String bullet = "\n - "; + for (OfflinePlayer opl : team.getPlayers()) + { + if (!p.getGameManager().isGameRunning()) + { + players += bullet + opl.getName(); + } + else + { + if (p.getGameManager().isPlayerDead(opl.getUniqueId())) + { + /// Displayed in team tooltip of the chat team selector for a dead player + players += bullet + I.t("{0} ({red}dead{reset})", opl.getName()); + } + else + { + /// Displayed in team tooltip of the chat team selector for an alive player + players += bullet + I.t("{0} ({green}alive{reset})", opl.getName()); + } + } + } + } + + RawMessage.send(player, new RawText("") + .then( + MAX_PLAYERS_PER_TEAM != 0 + /// Team count with max players (ex. [3/5]) followed in-game by the team name. {0} = current count, {1} = max. + ? I.t("{gray}[{white}{0}{gray}/{white}{1}{gray}]", String.valueOf(team.getSize()), String.valueOf(MAX_PLAYERS_PER_TEAM)) + /// Team count without max players (ex. [3]) followed in-game by the team name. {0} = current count. + : I.t("{gray}[{white}{0}{gray}]", String.valueOf(team.getSize())) + ) + .hover(new RawText(I.tn("{0} player in this team", "{0} players in this team", team.getPlayers().size(), team.getPlayers().size()) + players)) + + .then(" ") + + .then(team.getName()) + .color(team.getColor().toChatColor()) + .command("/join " + team.getName()) + .style(team.containsPlayer(player) ? ChatColor.BOLD : null) + .hover(new RawText( + team.containsPlayer(player) + /// Tooltip on the chat team selector GUI when the player is in the team. {0} = team display name. + ? I.t("You are in the team {0}", team.getDisplayName()) + /// Tooltip on the chat team selector GUI when the player is not in the team. {0} = team display name. + : I.t("Click here to join the team {0}", team.getDisplayName()) + )) + + .build() + ); + } + + if (p.getTeamManager().getTeamForPlayer(player) != null && player.hasPermission("uh.player.leave.self")) + { + RawMessage.send(player, + new RawText(I.t("{darkred}[×] {red}Click here to leave your team")).command("/leave") + ); + } + else + { + player.sendMessage(I.t("{gray}Run /join to display this again")); + } + } + else + { + // No teams. + player.sendMessage(I.t("{ce}There isn't any team available.")); + } + + player.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); + } + + + /** + * Displays the team of the given player in his action bar. + * If the player is not in a team, or the game is started, does nothing. + * + * @param player The player. + */ + public void displayTeamInActionBar(Player player) + { + UHTeam team = getTeamForPlayer(player); + if (team == null) return; + + displayTeamInActionBar(player, team); + } + + /** + * Displays the team of the given player in his action bar. + * If the player is not in a team, or the game is started, does nothing. + * + * Internal use when an instance of the team is accessible (avoids lookup). + * + * @param player The player. + * @param team The team. + */ + void displayTeamInActionBar(Player player, UHTeam team) + { + if (!UHCReloaded.get().getGameManager().isGameStarted()) + ActionBar.sendPermanentMessage(player, I.t("{gold}Your team: {0}", team.getDisplayName())); + } + + /** + * Updates the teams GUIs. Called when a team is created, deleted, or updated, + * so the GUIs update in real time. + */ + void updateGUIs() + { + Gui.update(TeamsSelectorGUI.class); + Gui.update(TeamEditGUI.class); + Gui.update(TeamEditMembersGUI.class); + Gui.update(TeamEditDeleteGUI.class); + } + + + @ConfigurationValueHandler + static public TeamColor handleTeamColorValue(String value) throws ConfigurationParseException + { + TeamColor color = TeamColor.fromString(value); + if(color == null) + throw new ConfigurationParseException("Invalid team color name.", value); + + return color; + } + + @ConfigurationValueHandler + static public UHTeam handleTeamValue(String str) throws ConfigurationParseException + { + return handleTeamValue(Arrays.asList(str.split(","))); + } + + @ConfigurationValueHandler + static public UHTeam handleTeamValue(List list) throws ConfigurationParseException + { + if(list.size() < 1) + throw new ConfigurationParseException("Not enough values, at least 1 required.", list); + if(list.size() > 2) + throw new ConfigurationParseException("Too many values, at most 2 (color, name) can be used.", list); + + if(list.size() == 1) + { + return new UHTeam(list.get(0).toString().trim(), handleTeamColorValue(list.get(0).toString())); + } + else + { + return new UHTeam(list.get(1).toString().trim(), handleTeamColorValue(list.get(0).toString())); + } + } + + @ConfigurationValueHandler + static public UHTeam handleTeamValue(Map map) throws ConfigurationParseException + { + TeamColor color = map.containsKey("color") ? handleTeamColorValue(map.get("color").toString()) : TeamColor.RANDOM; + Object name = map.containsKey("name") ? map.get("name") : map.get("color"); + + if(name == null) + throw new ConfigurationParseException("Either color or name must be specified", map); + + return new UHTeam(name.toString(), color); + } + + +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java new file mode 100644 index 0000000..0367017 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java @@ -0,0 +1,617 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.teams; + +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.UHConfig; +import eu.carrade.amaury.UHCReloaded.utils.ColorsUtils; +import eu.carrade.amaury.UHCReloaded.utils.TextUtils; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.tools.items.ItemStackBuilder; +import fr.zcraft.zlib.tools.items.TextualBanners; +import fr.zcraft.zlib.tools.text.ActionBar; +import org.apache.commons.lang.Validate; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BannerMeta; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.UUID; + + +public class UHTeam +{ + private static final boolean BANNER_SHAPE_WRITE_LETTER = UHConfig.TEAMS_OPTIONS.BANNER.SHAPE.WRITE_LETTER.get(); + private static final boolean BANNER_SHAPE_ADD_BORDER = UHConfig.TEAMS_OPTIONS.BANNER.SHAPE.ADD_BORDER.get(); + + private UHCReloaded plugin = UHCReloaded.get(); + + private String name = null; + private String internalName = null; + private String displayName = null; + private TeamColor color = null; + private ItemStack defaultBanner = null; + private ItemStack banner = null; + + private HashSet<UUID> players = new HashSet<>(); + + + public UHTeam(String name, TeamColor color) + { + Validate.notNull(name, "The name cannot be null."); + + // We use a random internal name because the name of a team, in Minecraft vanilla, is limited + // (16 characters max). + Random rand = new Random(); + this.internalName = String.valueOf(rand.nextInt(99999999)) + String.valueOf(rand.nextInt(99999999)); + + Scoreboard sb = this.plugin.getScoreboardManager().getScoreboard(); + Team t = sb.registerNewTeam(this.internalName); + + t.setSuffix(ChatColor.RESET.toString()); + t.setCanSeeFriendlyInvisibles(UHConfig.TEAMS_OPTIONS.CAN_SEE_FRIENDLY_INVISIBLES.get()); + t.setAllowFriendlyFire(UHConfig.TEAMS_OPTIONS.ALLOW_FRIENDLY_FIRE.get()); + + setName(name, true); + setColor(color); + updateDefaultBanner(); + } + + /** + * @deprecated Use {@link #UHTeam(String, TeamColor)} instead. + */ + @Deprecated + public UHTeam(String name, TeamColor color, UHCReloaded plugin) + { + this(name, color); + } + + /** + * Returns the name of the team. + * + * Can include spaces. + * + * @return The name. + */ + public String getName() + { + return name; + } + + public void setName(String name) + { + setName(name, false); + } + + /** + * Changes the name of this team. + * + * @param name The new name. + * @param silent if {@code true}, the players will not be notified. + */ + public void setName(String name, boolean silent) + { + if (name == null || (this.name != null && this.name.equals(name))) + return; + + this.name = name; + + updateDisplayName(); + updateDefaultBanner(); + + plugin.getTeamManager().updateGUIs(); + + for (Player player : getOnlinePlayers()) + { + if (!silent) + player.sendMessage(I.t("{cs}Your team is now called {0}{cs}.", displayName)); + + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + plugin.getTeamManager().displayTeamInActionBar(player, this); + } + } + + /** + * Returns the display name of the team. + * + * This name is: + * - if the team is uncolored, the name of the team; + * - else, the name of the team with: + * - before, the color of the team; + * - after, the "reset" formatting mark (§r). + * + * @return The display name. + */ + public String getDisplayName() + { + return displayName; + } + + private void updateDisplayName() + { + displayName = (color != null) ? color.toChatColor() + name + ChatColor.RESET : name; + + Team t = plugin.getScoreboardManager().getScoreboard().getTeam(internalName); + if (t != null) + t.setDisplayName(displayName.substring(0, Math.min(displayName.length(), 32))); + } + + /** + * Returns the players inside this team. + * + * @return The players. + */ + public Set<OfflinePlayer> getPlayers() + { + HashSet<OfflinePlayer> playersList = new HashSet<>(); + + for (UUID id : players) + { + Player player = plugin.getServer().getPlayer(id); + if (player != null) + { + playersList.add(player); + } + else + { + playersList.add(plugin.getServer().getOfflinePlayer(id)); + } + } + + return playersList; + } + + /** + * Returns the online players inside this team. + * + * @return The online players. + */ + public Set<Player> getOnlinePlayers() + { + HashSet<Player> playersList = new HashSet<>(); + + for (UUID id : players) + { + Player player = plugin.getServer().getPlayer(id); + if (player != null && player.isOnline()) + { + playersList.add(player); + } + } + + return playersList; + } + + /** + * Returns the UUIDs of the players inside this team. + * + * @return The UUIDs of the players. + */ + @SuppressWarnings ("unchecked") + public Set<UUID> getPlayersUUID() + { + return Collections.unmodifiableSet(players); + } + + /** + * Returns the UUIDs of the online players inside this team. + * + * @return The UUID of the online players. + */ + public Set<UUID> getOnlinePlayersUUID() + { + HashSet<UUID> playersList = new HashSet<>(); + + for (UUID id : players) + { + Player player = plugin.getServer().getPlayer(id); + if (player != null && player.isOnline()) + { + playersList.add(id); + } + } + + return playersList; + } + + /** + * Returns the size of this team. + * + * @return The size. + */ + public int getSize() + { + return players.size(); + } + + /** + * Returns true if the team is empty. + * + * @return The emptiness. + */ + public boolean isEmpty() + { + return getSize() == 0; + } + + public boolean isFull() + { + return plugin.getTeamManager().getMaxPlayersPerTeam() != 0 && getSize() >= plugin.getTeamManager().getMaxPlayersPerTeam(); + } + + /** + * Adds a player inside this team. + * + * @param player The player to add. + */ + public void addPlayer(OfflinePlayer player) + { + addPlayer(player, false); + } + + /** + * Adds a player inside this team. + * + * @param player The player to add. + * @param silent If true, the player will not be notified about this. + */ + public void addPlayer(OfflinePlayer player, boolean silent) + { + Validate.notNull(player, "The player cannot be null."); + + if (plugin.getTeamManager().getMaxPlayersPerTeam() != 0 + && this.players.size() >= plugin.getTeamManager().getMaxPlayersPerTeam()) + { + throw new RuntimeException("The team " + getName() + " is full"); + } + + plugin.getTeamManager().removePlayerFromTeam(player, true); + + players.add(player.getUniqueId()); + plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).addPlayer(player); + + plugin.getTeamManager().colorizePlayer(player); + + plugin.getTeamManager().updateGUIs(); + + if (player.isOnline()) + { + if (!silent) + ((Player) player).sendMessage(I.t("{aqua}You are now in the {0}{aqua} team.", getDisplayName())); + + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + plugin.getTeamManager().displayTeamInActionBar((Player) player, this); + } + } + + /** + * Removes a player from this team. + * + * Nothing is done if the player wasn't in this team. + * + * @param player The player to remove. + */ + public void removePlayer(OfflinePlayer player) + { + removePlayer(player, false); + } + + /** + * Removes a player from this team. + * + * Nothing is done if the player wasn't in this team. + * + * @param player The player to remove. + * @param silent If true, the player will not be notified. + */ + public void removePlayer(OfflinePlayer player, boolean silent) + { + Validate.notNull(player, "The player cannot be null."); + + players.remove(player.getUniqueId()); + unregisterPlayer(player, silent); + + plugin.getTeamManager().updateGUIs(); + } + + /** + * Unregisters a player from the scoreboard and uncolorizes the pseudo. + * + * Internal use, avoids a ConcurrentModificationException in this.deleteTeam() + * (this.players is listed and emptied simultaneously, else). + */ + private void unregisterPlayer(OfflinePlayer player, boolean silent) + { + if (player == null) return; + + plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).removePlayer(player); + plugin.getTeamManager().colorizePlayer(player); + + if (player.isOnline()) + { + if (!silent) + ((Player) player).sendMessage(I.t("{darkaqua}You are no longer part of the {0}{darkaqua} team.", getDisplayName())); + + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + ActionBar.removeMessage((Player) player, true); + } + } + + /** + * Deletes this team. + * + * The players inside the team are left without any team. + */ + public void deleteTeam() + { + // We removes the players from the team (scoreboard team too) + for (UUID id : players) + unregisterPlayer(plugin.getServer().getOfflinePlayer(id), false); + + players.clear(); + + // Then the scoreboard team is deleted. + plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).unregister(); + } + + /** + * Returns true if the given player is in this team. + * + * @param player The player to check. + * @return true if the given player is in this team. + */ + public boolean containsPlayer(Player player) + { + Validate.notNull(player, "The player cannot be null."); + + return players.contains(player.getUniqueId()); + } + + /** + * Returns true if the player with the given UUID is in this team. + * + * @param id The UUID of the player to check. + * @return true if the given player is in this team. + */ + public boolean containsPlayer(UUID id) + { + Validate.notNull(id, "The player cannot be null."); + + return players.contains(id); + } + + /** + * Teleports the entire team to the given location. + * + * @param location The location. + */ + public void teleportTo(Location location) + { + Validate.notNull(location, "The location cannot be null."); + + for (UUID id : players) + { + Player player = plugin.getServer().getPlayer(id); + if (player != null && player.isOnline()) + { + player.teleport(location, TeleportCause.PLUGIN); + } + } + } + + /** + * @return the color of the team. + */ + public TeamColor getColor() + { + return color; + } + + /** + * Updates the team color. + * + * @param color The new color. + */ + public void setColor(TeamColor color) + { + // We don't use generateColor directly because we want to keep the "null" color. + if (color == TeamColor.RANDOM) this.color = plugin.getTeamManager().generateColor(color); + else this.color = color; + + updateDisplayName(); + + // The team color needs to be updated + if (this.color != null) + { + Team t = plugin.getScoreboardManager().getScoreboard().getTeam(internalName); + if (t != null) + t.setPrefix(this.color.toChatColor().toString()); + } + + // The players names too + for (Player player : getOnlinePlayers()) + { + plugin.getTeamManager().colorizePlayer(player); + + // Also we update the action bar if needed + if (UHConfig.BEFORE_START.TEAM_IN_ACTION_BAR.get()) + plugin.getTeamManager().displayTeamInActionBar(player, this); + } + + // The default banner too + updateDefaultBanner(); + + plugin.getTeamManager().updateGUIs(); + } + + + /** + * Generates and return the default banner for this team, following the + * banners options in the configuration file. + * + * @return the generated banner. + */ + public ItemStack getDefaultBanner() + { + ItemStack banner; + DyeColor dye = ColorsUtils.chat2Dye(color.toChatColor()); + + if (BANNER_SHAPE_WRITE_LETTER) + { + banner = TextualBanners.getCharBanner(Character.toUpperCase(TextUtils.getInitialLetter(name)), dye, BANNER_SHAPE_ADD_BORDER); + } + else + { + banner = new ItemStack(Material.BANNER); + BannerMeta meta = (BannerMeta) banner.getItemMeta(); + meta.setBaseColor(dye); + banner.setItemMeta(meta); + } + + return banner; + } + + /** + * Regenerates the default banner. + */ + private void updateDefaultBanner() + { + // Avoid updating in the constructor before all the object is populated. + if (name != null && color != null) + defaultBanner = getDefaultBanner(); + } + + /** + * Updates this team's banner. + * + * @param banner The new banner. {@code null} to use the default banner. + */ + public void setBanner(ItemStack banner) + { + if (banner == null) + { + this.banner = null; + return; + } + + if (banner.getType() != Material.BANNER) + throw new IllegalArgumentException("A banner is required"); + + this.banner = new ItemStackBuilder(banner.clone()) + .title(displayName) + .amount(1) + .hideAttributes() + .item(); + + if (banner.hasItemMeta()) + { + BannerMeta meta = (BannerMeta) this.banner.getItemMeta(); + meta.setBaseColor(((BannerMeta) banner.getItemMeta()).getBaseColor()); + this.banner.setItemMeta(meta); + } + + plugin.getTeamManager().updateGUIs(); + } + + /** + * Updates this team's banner. + * + * @param banner The new banner. {@code null} to use the default banner. + */ + public void setBanner(BannerMeta banner) + { + if (banner == null) + { + this.banner = null; + return; + } + + this.banner = new ItemStackBuilder(Material.BANNER) + .title(displayName) + .amount(1) + .hideAttributes() + .item(); + + this.banner.setItemMeta(banner.clone()); + + plugin.getTeamManager().updateGUIs(); + } + + /** + * Returns this team's banner. + * + * @return the banner. + */ + public ItemStack getBanner() + { + return banner == null ? defaultBanner : banner; + } + + + @Override + public int hashCode() + { + return ((name == null) ? 0 : name.hashCode()); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof UHTeam)) + return false; + UHTeam other = (UHTeam) obj; + if (name == null) + { + if (other.name != null) + return false; + } + else if (!name.equals(other.name)) + return false; + return true; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/timers/TimerManager.java b/src/main/java/eu/carrade/amaury/UHCReloaded/timers/TimerManager.java new file mode 100644 index 0000000..95e5691 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/timers/TimerManager.java @@ -0,0 +1,219 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.timers; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; + + +public class TimerManager +{ + private Map<String, UHTimer> timers = new ConcurrentHashMap<>(); + private UHTimer mainTimer = null; + + /** + * Cached list of the running timers + */ + private Map<String, UHTimer> runningTimers = new ConcurrentHashMap<>(); + + /** + * List of the timers to resume if running timers are paused. + * + * @see {@link #pauseAllRunning(boolean)}. + */ + private Set<UHTimer> timersToResume = new CopyOnWriteArraySet<>(); + + + /** + * Registers the main timer, used to display the episodes countdown. + * + * @param timer The timer. + */ + public void registerMainTimer(UHTimer timer) + { + this.mainTimer = timer; + timer.setRegistered(true); + } + + /** + * Returns the main timer, used to display the episodes countdown. + * + * @return The main timer. + */ + public UHTimer getMainTimer() + { + return this.mainTimer; + } + + /** + * Registers a timer. + * + * @param timer The timer to register. + * @throws IllegalArgumentException if a timer with the same name is already registered. + */ + public void registerTimer(UHTimer timer) + { + + if (timers.get(timer.getName()) != null) + { + throw new IllegalArgumentException("A timer with the name " + timer.getName() + " is already registered."); + } + + timers.put(timer.getName(), timer); + + timer.setRegistered(true); + } + + /** + * Unregisters a timer. + * <p> + * If the timer was not registered, nothing is done. + * + * @param timer The timer to unregister. + */ + public void unregisterTimer(UHTimer timer) + { + timers.remove(timer.getName()); + runningTimers.remove(timer.getName()); + + timer.setRegistered(false); + } + + /** + * Updates the internal list of started timers. + */ + public void updateStartedTimersList() + { + runningTimers = new HashMap<>(); + + if (getMainTimer() != null && getMainTimer().isRunning()) + { + runningTimers.put(getMainTimer().getName(), getMainTimer()); + } + + for (UHTimer timer : timers.values()) + { + if (timer.isRunning()) + { + runningTimers.put(timer.getName(), timer); + } + } + } + + /** + * Returns a timer by his name. + * + * @param name The name of the timer. + * + * @return The timer, or null if there isn't any timer with this name. + */ + public UHTimer getTimer(String name) + { + return timers.get(name); + } + + /** + * Returns a collection containing the registered timers. + * + * @return The collection. + */ + public Collection<UHTimer> getTimers() + { + return timers.values(); + } + + /** + * Returns a collection containing the running timers. + * + * @return The collection. + */ + public Collection<UHTimer> getRunningTimers() + { + return runningTimers.values(); + } + + /** + * Pauses (or resumes) all the running timers. + * + * @param paused If true, all the timers will be paused. Else, resumed. + */ + public void pauseAll(boolean paused) + { + for (UHTimer timer : getRunningTimers()) + { + timer.setPaused(paused); + } + + if (!paused) + { + // If we restart all the timers regardless to their previous state, + // this data is meaningless. + timersToResume.clear(); + } + } + + /** + * Pauses (or resumes) all the running timers. + * <p> + * This method will only resume the previously-running timers. + * + * @param paused If true, all the timers will be paused. Else, resumed. + */ + public void pauseAllRunning(boolean paused) + { + if (paused) + { + for (UHTimer timer : getRunningTimers()) + { + if (!timer.isPaused()) + { + timer.setPaused(true); + timersToResume.add(timer); + } + } + } + else + { + for (UHTimer timer : timersToResume) + { + timer.setPaused(false); + } + + timersToResume.clear(); + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java b/src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java new file mode 100644 index 0000000..04edd00 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java @@ -0,0 +1,418 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.timers; + +import eu.carrade.amaury.UHCReloaded.events.TimerEndsEvent; +import eu.carrade.amaury.UHCReloaded.events.TimerStartsEvent; +import fr.zcraft.zlib.components.i18n.I; +import org.apache.commons.lang.Validate; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; + +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.UUID; + + +/** + * Represents a timer. + * + * @author Amaury Carrade + */ +public class UHTimer +{ + private static final NumberFormat formatter = new DecimalFormat("00"); + + private UUID id = null; + private String name = null; + private Boolean registered = false; + private Boolean running = false; + private Boolean displayed = false; + + private Long startTime = 0l; + private Integer duration = 0; // seconds + + // Cached values + private Integer hoursLeft = 0; + private Integer minutesLeft = 0; + private Integer secondsLeft = 0; + + // Old values, used by the scoreboard to reset the scores. + private Integer oldHoursLeft = -1; + private Integer oldMinutesLeft = -1; + private Integer oldSecondsLeft = -1; + + // Pause + private Boolean paused = false; + private Long pauseTime = 0l; + + // Display this timer following the format "hh:mm:ss"? + private Boolean displayHoursInTimer = false; + + + public UHTimer(String name) + { + Validate.notNull(name, "The name cannot be null"); + + this.id = UUID.randomUUID(); // only used as a hashCode. + this.name = name; + } + + /** + * Sets the duration of the timer, in seconds. + * + * @param seconds The duration. + */ + public void setDuration(int seconds) + { + this.duration = seconds; + + this.hoursLeft = (int) Math.floor(this.duration / 3600); + this.minutesLeft = (int) (Math.floor(this.duration / 60) - (this.hoursLeft * 60)); + this.secondsLeft = this.duration - (this.minutesLeft * 60 + this.hoursLeft * 3600); + + this.displayHoursInTimer = (this.hoursLeft != 0); + } + + /** + * Starts this timer. + * + * If this is called while the timer is running, the timer is restarted. + */ + public void start() + { + this.running = true; + this.startTime = System.currentTimeMillis(); + + Bukkit.getServer().getPluginManager().callEvent(new TimerStartsEvent(this)); + } + + /** + * Stops this timer. + */ + public void stop() + { + stop(false); + } + + /** + * Stops this timer. + * + * @param wasUp If true, the timer was stopped because the timer was up. + */ + private void stop(boolean wasUp) + { + TimerEndsEvent event = new TimerEndsEvent(this, wasUp); + Bukkit.getServer().getPluginManager().callEvent(event); + + if (isRegistered()) + { + if (event.getRestart()) + { + start(); + } + else + { + this.running = false; + this.startTime = 0l; + + this.hoursLeft = 0; + this.minutesLeft = 0; + this.secondsLeft = 0; + + this.oldHoursLeft = 0; + this.oldMinutesLeft = 0; + this.oldSecondsLeft = 0; + } + } + } + + /** + * Updates the timer. + */ + public void update() + { + if (running && !paused) + { + oldHoursLeft = hoursLeft; + oldMinutesLeft = minutesLeft; + oldSecondsLeft = secondsLeft; + + long timeSinceStart = System.currentTimeMillis() - this.startTime; // ms + + if (timeSinceStart >= getDuration() * 1000) + { + stop(true); + } + else + { + Integer countSecondsLeft = (int) (getDuration() - Math.floor(timeSinceStart / 1000)); + + secondsLeft = countSecondsLeft % 60; + minutesLeft = (countSecondsLeft % 3600) / 60; + hoursLeft = (int) Math.floor(countSecondsLeft / 3600); + } + } + } + + /** + * Pauses (or restarts after a pause) the timer. + * <p> + * If the timer is not running, nothing is done. + * + * @param pause If true the timer will be paused. + */ + public void setPaused(boolean pause) + { + if (this.running) + { + // The pause is only set once (as example if the user executes /uh freeze all twice). + if (pause && !this.paused) + { + this.paused = true; + this.pauseTime = System.currentTimeMillis(); + } + + if (!pause && this.paused) + { + // We have to add to the time of the start of the episode the elapsed time + // during the pause. + this.startTime += (System.currentTimeMillis() - this.pauseTime); + this.pauseTime = 0l; + + this.paused = false; + } + } + } + + /** + * Checks if the timer is registered in the TimerManager. + * + * @return true if the timer is registered. + */ + public Boolean isRegistered() + { + return registered; + } + + /** + * Marks a timer as registered, or not. + * + * @param registered true if the timer is now registered. + */ + protected void setRegistered(Boolean registered) + { + this.registered = registered; + } + + /** + * Returns the name of the timer. + * + * @return The name. + */ + public String getName() + { + return name; + } + + /** + * Returns the display name of the timer. + * <p> + * The display name is the name with all &-based color codes replaced by §-based ones. + * + * @return The name. + */ + public String getDisplayName() + { + return ChatColor.translateAlternateColorCodes('&', name); + } + + + /** + * Checks if the timer is currently running. + * + * @return true if the timer is running. + */ + public Boolean isRunning() + { + return running; + } + + /** + * Checks if the timer is currently displayed in the scoreboard. + * + * @return {@code true} if displayed. + */ + public Boolean isDisplayed() + { + return displayed; + } + + /** + * Display or hide this timer in/from the scoreboard. + * + * @param displayed {@code true} to display, and {@code false} to hide. + */ + public void setDisplayed(Boolean displayed) + { + this.displayed = displayed; + } + + /** + * Returns the duration of the timer, in seconds. + * + * @return The duration. + */ + public Integer getDuration() + { + return duration; + } + + /** + * Returns the number of hours left until the end of this countdown. + * + * @return The number of hours left. + */ + public Integer getHoursLeft() + { + return hoursLeft; + } + + /** + * Returns the number of minutes left until the end of this countdown. + * + * @return The number of minutes left. + */ + public Integer getMinutesLeft() + { + return minutesLeft; + } + + /** + * Returns the number of seconds left until the end of this countdown. + * + * @return The number of seconds left. + */ + public Integer getSecondsLeft() + { + return secondsLeft; + } + + /** + * Returns the number of hours left until the end of this countdown, before the last update. + * <p> + * Used by the scoreboard, to remove the old score. + * + * @return The old number of hours left, or -1 if the timer was never updated. + */ + public Integer getOldHoursLeft() + { + return oldHoursLeft; + } + + /** + * Returns the number of minutes left until the end of this countdown, before the last update. + * <p> + * Used by the scoreboard, to remove the old score. + * + * @return The old number of minutes left, or -1 if the timer was never updated. + */ + public Integer getOldMinutesLeft() + { + return oldMinutesLeft; + } + + /** + * Returns the number of seconds left until the end of this countdown, before the last update. + * <p> + * Used by the scoreboard, to remove the old score. + * + * @return The old number of seconds left, or -1 if the timer was never updated. + */ + public Integer getOldSecondsLeft() + { + return oldSecondsLeft; + } + + /** + * Checks if this timer is paused. + * + * @return true if the timer is paused. + */ + public Boolean isPaused() + { + return paused; + } + + /** + * Returns true if this timer is displayed as "hh:mm:ss" in the scoreboard. + * + * @return true if this timer is displayed as "hh:mm:ss" in the scoreboard. + */ + public Boolean getDisplayHoursInTimer() + { + return displayHoursInTimer; + } + + @Override + public boolean equals(Object other) + { + return other instanceof UHTimer && ((UHTimer) other).getName().equals(this.getName()); + } + + @Override + public String toString() + { + return toString(displayHoursInTimer); + } + + public String toString(boolean displayHours) + { + if (displayHours) + { + /// Timer. {0} = hours; {1} = minutes; {2} = seconds. + return I.t("{0}{gray}:{white}{1}{gray}:{white}{2}", formatter.format(hoursLeft), formatter.format(minutesLeft), formatter.format(secondsLeft)); + } + else + { + /// Timer. {0} = minutes; {1} = seconds. + return I.t("{white}{0}{gray}:{white}{1}", formatter.format(minutesLeft), formatter.format(secondsLeft)); + } + } + + @Override + public int hashCode() + { + return id.hashCode(); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/utils/ColorsUtils.java b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/ColorsUtils.java new file mode 100644 index 0000000..4b7470d --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/ColorsUtils.java @@ -0,0 +1,90 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.utils; + +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; + + +public final class ColorsUtils +{ + private ColorsUtils() {} + + public static DyeColor chat2Dye(ChatColor chatColor) + { + switch (chatColor) + { + case BLACK: + return DyeColor.BLACK; + + case BLUE: + case DARK_BLUE: + return DyeColor.BLUE; + + case DARK_GREEN: + return DyeColor.GREEN; + + case DARK_AQUA: + return DyeColor.CYAN; + + case DARK_RED: + return DyeColor.RED; + + case DARK_PURPLE: + return DyeColor.PURPLE; + + case GOLD: + case YELLOW: + return DyeColor.YELLOW; + + case GRAY: + case DARK_GRAY: + return DyeColor.SILVER; + + case GREEN: + return DyeColor.LIME; + + case AQUA: + return DyeColor.LIGHT_BLUE; + + case RED: + return DyeColor.ORANGE; + + case LIGHT_PURPLE: + return DyeColor.PINK; + + // White, reset & formatting + default: + return DyeColor.WHITE; + } + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/utils/OfflinePlayersComparator.java b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/OfflinePlayersComparator.java new file mode 100644 index 0000000..56d240c --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/OfflinePlayersComparator.java @@ -0,0 +1,51 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.utils; + +import org.bukkit.OfflinePlayer; + +import java.util.Comparator; + + +public class OfflinePlayersComparator implements Comparator<OfflinePlayer> +{ + @Override + public int compare(OfflinePlayer player1, OfflinePlayer player2) + { + if (player1.isOnline() == player2.isOnline()) + return player1.getName().toLowerCase().compareTo(player2.getName().toLowerCase()); + else if (player1.isOnline()) + return -1; + else + return 1; + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/utils/TextUtils.java b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/TextUtils.java new file mode 100644 index 0000000..d2967e3 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/TextUtils.java @@ -0,0 +1,140 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.utils; + +import com.google.common.collect.Sets; +import org.apache.commons.lang.WordUtils; + +import java.util.Set; + + +public final class TextUtils +{ + private TextUtils() {} + + private static final Set<String> SMALL_WORDS = Sets.newHashSet( + // English + "the", "a", "it", "they", "them", "an", "all", "of", "this", "is", "not", "that", + // French + "un", "une", "le", "la", "les", "des", "je", "tu", "il", "elle", "on", "nous", "vous", "ils", "elles", "ça", "ca", "sa", "cela", "lui", "l" + ); + + /** + * Tries to find a single alphanumeric character best representing this string. + * + * @param text The string. + * @return An alphanumeric character. A space if the initial text is blank. + */ + public static char getInitialLetter(String text) + { + text = toAlphanumeric(text); + + if (text == null || text.isEmpty()) + return ' '; + + // We try to find the main word of the sentence, based on four principles: + // - the main word is likely to be at the beginning of the string; + // - the main word is likely to be pretty long; + // - the main word is unlikely to be a single-letter word; + // - the main word is unlikely to be an article like “The”. + + String[] words = text.split(" "); + + Integer bestScore = Integer.MIN_VALUE; + String bestWord = " "; + + Integer averageWordLength = 0; + for (String word : words) + averageWordLength += word.length(); + + averageWordLength /= words.length; + + for (int i = 0, wordsCount = words.length; i < wordsCount; i++) + { + String word = words[i].toLowerCase(); + Integer score = 0; + + if (i < 3) + score += 5; + + if (word.length() == 1) + score -= 3; + else if (word.length() >= averageWordLength) + score += 5; + + if (SMALL_WORDS.contains(word)) + score -= 10; + + if (score > bestScore) + { + bestScore = score; + bestWord = words[i]; + } + } + + return bestWord.charAt(0); + } + + /** + * Removes all non-alphanumeric characters from the string. + * + * @param text The text. + * @return The same text, without non-alphanumeric characters. + */ + public static String toAlphanumeric(String text) + { + if (text == null) + return null; + + StringBuilder builder = new StringBuilder(); + for (Character character : text.toCharArray()) + { + // Convert all kind of spaces (unbreakable...) and apostrophes to basic spaces + if (Character.isSpaceChar(character) || character.equals('\'')) + builder.append(" "); + + if (Character.isTitleCase(character)) + character = Character.toUpperCase(character); + + // Only keeps alphanumeric characters + if ((character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9')) + builder.append(character); + } + + return builder.toString(); + } + + public static String friendlyEnumName(Enum<?> enumConstant) + { + return WordUtils.capitalizeFully(enumConstant.name().replace("_", " ")); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHSound.java b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHSound.java new file mode 100644 index 0000000..dc7b5ad --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHSound.java @@ -0,0 +1,294 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.utils; + +import eu.carrade.amaury.UHCReloaded.UHConfig; +import fr.zcraft.zlib.components.configuration.ConfigurationValueHandler; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + + +/** + * Represents a sound, with volume and pitch. + * + * @author Amaury Carrade + */ +public class UHSound +{ + + private Sound sound = null; + private Float volume = 1f; + private Float pitch = 1f; + + /** + * Constructs a sound with volume = 1f and pitch = 1f. + * + * @param sound The sound. + */ + public UHSound(Sound sound) + { + this.sound = sound; + } + + public UHSound(Sound sound, Float volume, Float pitch) + { + this.sound = sound; + this.volume = volume; + this.pitch = pitch; + } + + /** + * Constructs a sound from a configuration section. + * <p> + * Format: + * <pre> + * key: + * name: string parsable as a sound. If not parsable, null used (i.e. no sound played). + * volume: decimal number + * pitch: decimal number + * </pre> + * + * @param config The configuration section. + */ + public UHSound(ConfigurationSection config) + { + if (config == null) + { + return; + } + + this.sound = string2Sound(config.getString("name")); + this.volume = (float) config.getDouble("volume"); + this.pitch = (float) config.getDouble("pitch"); + } + + /** + * Constructs a sound from a zLib sound configuration section. + * <p> + * Format: + * <pre> + * key: + * name: string parsable as a sound. If not parsable, null used (i.e. no sound played). + * volume: decimal number + * pitch: decimal number + * </pre> + * + * @param config The configuration section. + */ + public UHSound(UHConfig.SoundSection config) + { + if (config == null) + { + return; + } + + this.sound = config.NAME.get(); + this.volume = (float) config.VOLUME.get(); + this.pitch = (float) config.PITCH.get(); + } + + /** + * Plays the sound for the specified player. + * <p> + * The sound is played at the current location of the player. + * <p> + * If the sound is null, fails silently. + * + * @param player The player. + */ + public void play(Player player) + { + play(player, player.getLocation()); + } + + /** + * Plays the sound for the specified player, at the specified location. + * <p> + * If the sound is null, fails silently. + * + * @param player The player. + * @param location The location of the sound. + */ + public void play(Player player, Location location) + { + player.playSound(location, sound, volume, pitch); + } + + /** + * Plays this sound for all players, at the current location of the players. + */ + public void broadcast() + { + for (Player player : Bukkit.getServer().getOnlinePlayers()) + { + play(player); + } + } + + public Sound getSound() + { + return sound; + } + + public void setSound(Sound sound) + { + this.sound = sound; + } + + public Float getVolume() + { + return volume; + } + + public void setVolume(Float volume) + { + this.volume = volume; + } + + public Float getPitch() + { + return pitch; + } + + public void setPitch(Float pitch) + { + this.pitch = pitch; + } + + @Override + public String toString() + { + return "UHSound [sound=" + sound + ", volume=" + volume + ", pitch=" + pitch + "]"; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((pitch == null) ? 0 : pitch.hashCode()); + result = prime * result + ((sound == null) ? 0 : sound.hashCode()); + result = prime * result + ((volume == null) ? 0 : volume.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof UHSound)) + { + return false; + } + UHSound other = (UHSound) obj; + if (pitch == null) + { + if (other.pitch != null) + { + return false; + } + } + else if (!pitch.equals(other.pitch)) + { + return false; + } + if (sound != other.sound) + { + return false; + } + if (volume == null) + { + if (other.volume != null) + { + return false; + } + } + else if (!volume.equals(other.volume)) + { + return false; + } + return true; + } + + + /** + * Converts a string to a Sound. + * <p> + * "<code>ANVIL_LAND</code>", "<code>Anvil Land</code>" and "<code>ANVIL Land</code>" are recognized as + * <code>Sound.ANVIL_LAND</code>, as example. + * + * @param soundName The text to be converted. + * @return The corresponding Sound, or null if there isn't any match. + */ + public static Sound string2Sound(String soundName) + { + if (soundName != null) + { + soundName = soundName.trim().toUpperCase().replace(" ", "_"); + try + { + return Sound.valueOf(soundName); + } + catch (IllegalArgumentException e) + { + String[] prefixes = new String[] {"BLOCK_", "ENTITY_", "ITEM_", "MUSIC_", "WEATHER_"}; + for (String prefix : prefixes) + { + try { return Sound.valueOf(prefix + soundName); } + catch(IllegalArgumentException ignored) {} + } + + // Non-existent sound + return null; + } + } + + return null; + } + + @ConfigurationValueHandler + public static Sound handleSoundValue(Object object) + { + return string2Sound(object.toString()); + } +} diff --git a/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHUtils.java b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHUtils.java new file mode 100644 index 0000000..f8ecf86 --- /dev/null +++ b/src/main/java/eu/carrade/amaury/UHCReloaded/utils/UHUtils.java @@ -0,0 +1,425 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ + +package eu.carrade.amaury.UHCReloaded.utils; + +import fr.zcraft.zlib.tools.Callback; +import fr.zcraft.zlib.tools.PluginLogger; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.FireworkEffect; +import org.bukkit.FireworkEffect.Builder; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.FireworkMeta; + +import java.util.Random; + + +public class UHUtils +{ + /** + * Extracts a string from a list of arguments, starting at the given index. + * + * @param args The raw arguments. + * @param startIndex The index of the first item in the returned string (first argument given: 0). + * + * @return The extracted string. + * + * @throws IllegalArgumentException if the index of the first element is out of the bounds of the arguments' list. + */ + public static String getStringFromCommandArguments(String[] args, int startIndex) + { + if (args.length < startIndex) + { + throw new IllegalArgumentException("The index of the first element is out of the bounds of the arguments' list."); + } + + String text = ""; + + for (int index = startIndex; index < args.length; index++) + { + if (index < args.length - 1) + { + text += args[index] + " "; + } + else + { + text += args[index]; + } + } + + return text; + } + + /** + * Converts a string to a number of seconds. + * <p> + * Format: + * <ul> + * <li><tt>mm</tt> – number of minutes;</li> + * <li><tt>mm:ss</tt> – minutes and seconds;</li> + * <li><tt>hh:mm:ss</tt> – hours, minutes and seconds.</li> + * </ul> + * + * + * @param text The text to be converted. + * @return The number of seconds represented by this string. + * + * @throws IllegalArgumentException if the text is not formatted as above. + * @throws NumberFormatException if the text between the colons cannot be converted in integers. + */ + public static int string2Time(String text) + { + String[] split = text.split(":"); + + if (text.isEmpty() || split.length > 3) + { + throw new IllegalArgumentException("Badly formatted string in string2time, formats allowed are mm, mm:ss or hh:mm:ss."); + } + + if (split.length == 1) // "mm" + { + return Integer.valueOf(split[0]) * 60; + } + else if (split.length == 2) // "mm:ss" + { + return Integer.valueOf(split[0]) * 60 + Integer.valueOf(split[1]); + } + else // "hh:mm:ss" + { + return Integer.valueOf(split[0]) * 3600 + Integer.valueOf(split[1]) * 60 + Integer.valueOf(split[2]); + } + } + + /** + * Converts a string to a number of seconds. + * + * Prints a warning if the format is invalid. + * + * @param text The text to be converted. + * @param defaultValue The default value returned if the format is invalid. + * + * @return The extracted seconds, or the default value if invalid. + * @see #string2Time(String) + */ + public static int string2Time(String text, Integer defaultValue) + { + try + { + return string2Time(text); + } + catch (IllegalArgumentException | NullPointerException e) + { + PluginLogger.warning("Invalid duration '{0}', using {1} seconds instead.", text, defaultValue); + return defaultValue; + } + } + + /** + * Converts a string to a boolean. + * + * <p> + * {@code true, on, 1, yes} (case insensitive) -> {@code true}.<br /> + * Anything else ({@code null} included) -> {@code false}. + * </p> + * + * @param raw The raw string. + * @return a boolean. + */ + public static boolean stringToBoolean(String raw) + { + return raw != null + && ( + raw.equalsIgnoreCase("true") + || raw.equalsIgnoreCase("on") + || raw.equalsIgnoreCase("1") + || raw.equalsIgnoreCase("yes") + ); + } + + /** + * @param integer An integer. + * @return A string representation of this integer, with an explicit "+" if positive. + */ + public static String integerToStringWithSign(int integer) + { + return (integer < 0 ? "" : "+") + String.valueOf(integer); + } + + + /** + * Finds a safe spot where teleport the player, and teleport the player to that spot. + * If a spot is not found, the player is not teleported, except if {@code force} is set to true. + * + * @param player + * @param location + * @param force If true the player will be teleported to the exact given location if there is no safe spot. + * @return true if the player was effectively teleported. + */ + public static boolean safeTP(Player player, Location location, boolean force) + { + // If the target is safe, let's go + if (isSafeSpot(location)) + { + player.teleport(location); + return true; + } + + // If the teleportation is forced, let's go + if (force) + { + player.teleport(location); + return true; + } + + Location safeSpot = searchSafeSpot(location); + + // A spot was found, let's teleport. + if (safeSpot != null) + { + player.teleport(safeSpot); + return true; + } + // No spot found; the teleportation is cancelled. + else + { + return false; + } + } + + /** + * Searches a safe spot where teleport the player, and teleport the player to that spot. + * If a spot is not found, the player is not teleported, except if {@code force} is set to true. + * + * @param player + * @param location + * @return true if the player was effectively teleported. + */ + public static boolean safeTP(Player player, Location location) + { + return safeTP(player, location, false); + } + + /** + * Searches a safe spot in the given location. + * + * The spot is in the same X;Z coordinates. + * + * @param location The location where to find a safe spot. + * @return A Location object representing the safe spot, or null if no safe spot is available. + */ + public static Location searchSafeSpot(Location location) + { + // We try to find a spot above or below the target + + Location safeSpot = null; + final int maxHeight = (location.getWorld().getEnvironment() == World.Environment.NETHER) ? 125 : location.getWorld().getMaxHeight() - 2; // (thx to WorldBorder) + + for (int yGrow = location.getBlockY(), yDecr = location.getBlockY(); yDecr >= 1 || yGrow <= maxHeight; yDecr--, yGrow++) + { + // Above? + if (yGrow < maxHeight) + { + Location spot = new Location(location.getWorld(), location.getBlockX(), yGrow, location.getBlockZ()); + if (isSafeSpot(spot)) + { + safeSpot = spot; + break; + } + } + + // Below? + if (yDecr > 1 && yDecr != yGrow) + { + Location spot = new Location(location.getWorld(), location.getX(), yDecr, location.getZ()); + if (isSafeSpot(spot)) + { + safeSpot = spot; + break; + } + } + } + + // A spot was found, we changes the pitch & yaw according to the original location. + if (safeSpot != null) + { + safeSpot.setPitch(location.getPitch()); + safeSpot.setYaw(location.getYaw()); + } + + return safeSpot; + } + + /** + * Checks if a given location is safe. + * A safe location is a location with two breathable blocks (aka transparent block or water) + * over something solid (or water). + * + * @param location + * @return true if the location is safe. + */ + public static boolean isSafeSpot(Location location) + { + Block blockCenter = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + Block blockAbove = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() + 1, location.getBlockZ()); + Block blockBelow = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()); + + if ((blockCenter.getType().isTransparent() || (blockCenter.isLiquid() && !blockCenter.getType().equals(Material.LAVA) && !blockCenter.getType().equals(Material.STATIONARY_LAVA))) + && (blockAbove.getType().isTransparent() || (blockAbove.isLiquid() && !blockAbove.getType().equals(Material.LAVA) && !blockCenter.getType().equals(Material.STATIONARY_LAVA)))) + { + // two breathable blocks: ok + + // The block below is solid, or liquid (but not lava) + return blockBelow.getType().isSolid() || blockBelow.getType().equals(Material.WATER) || blockBelow.getType().equals(Material.STATIONARY_WATER); + } + else + { + return false; + } + } + + + /** + * Spawns a random firework at the given location. + * + * Please note: because the power of a firework is an integer, the min/max heights + * are with a precision of ±5 blocks. + * + * @param location The location where the firework will be spawned. + * @param heightMin The minimal height of the explosion. + * @param heightMax The maximal height of the explosion. + * + * @return The random firework generated. + */ + public static Firework generateRandomFirework(Location location, int heightMin, int heightMax) + { + Random rand = new Random(); + + Firework firework = (Firework) location.getWorld().spawnEntity(location, EntityType.FIREWORK); + FireworkMeta meta = firework.getFireworkMeta(); + + int effectsCount = rand.nextInt(3) + 1; + + for (int i = 0; i < effectsCount; i++) + { + meta.addEffect(generateRandomFireworkEffect()); + } + + // One level of power is half a second of flight time. + // In half a second, a firework fly ~5 blocks. + // So, one level of power = ~5 blocks. + meta.setPower((int) Math.min(Math.floor((heightMin / 5) + rand.nextInt(heightMax / 5)), 128D)); + + firework.setFireworkMeta(meta); + + return firework; + } + + /** + * Generates a random firework effect. + * + * @return The firework effect. + */ + private static FireworkEffect generateRandomFireworkEffect() + { + Random rand = new Random(); + Builder fireworkBuilder = FireworkEffect.builder(); + + int colorCount = rand.nextInt(3) + 1; + int trailCount = rand.nextInt(3) + 1; + + fireworkBuilder.flicker(rand.nextInt(3) == 1); + fireworkBuilder.trail(rand.nextInt(3) == 1); + + for (int i = 0; i < colorCount; i++) + { + fireworkBuilder.withColor(generateRandomColor()); + } + + for (int i = 0; i < trailCount; i++) + { + fireworkBuilder.withFade(generateRandomColor()); + } + + // Random shape + FireworkEffect.Type[] types = FireworkEffect.Type.values(); + fireworkBuilder.with(types[rand.nextInt(types.length)]); + + return fireworkBuilder.build(); + } + + /** + * Generates a random color. + * + * @return The color. + */ + private static Color generateRandomColor() + { + Random rand = new Random(); + return Color.fromBGR(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)); + } + + /** + * Calls a callback if it is defined (non-{@code null}). + * + * @param callback The callback + * @param argument The callback's argument. + * @param <T> The callback's argument type. + */ + public static <T> void callIfDefined(Callback<T> callback, T argument) + { + if (callback != null) callback.call(argument); + } + + /** + * Returns the overworld. + * + * @return the... overworld? + */ + public static World getOverworld() + { + for (World world : Bukkit.getServer().getWorlds()) + { + if (world.getEnvironment() != World.Environment.NETHER && world.getEnvironment() != World.Environment.THE_END) + { + return world; + } + } + return null; + } +} diff --git a/src/main/java/me/azenet/UHPlugin/UHGameManager.java b/src/main/java/me/azenet/UHPlugin/UHGameManager.java deleted file mode 100644 index 70ecf69..0000000 --- a/src/main/java/me/azenet/UHPlugin/UHGameManager.java +++ /dev/null @@ -1,1012 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin; - -import me.azenet.UHPlugin.events.EpisodeChangedCause; -import me.azenet.UHPlugin.events.UHEpisodeChangedEvent; -import me.azenet.UHPlugin.events.UHGameStartsEvent; -import me.azenet.UHPlugin.events.UHPlayerResurrectedEvent; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.misc.ProTipsSender; -import me.azenet.UHPlugin.task.FireworksOnWinnersTask; -import me.azenet.UHPlugin.task.TeamStartTask; -import me.azenet.UHPlugin.teams.TeamColor; -import me.azenet.UHPlugin.teams.TeamManager; -import me.azenet.UHPlugin.teams.UHTeam; -import me.azenet.UHPlugin.timers.UHTimer; -import me.azenet.UHPlugin.utils.UHSound; -import me.azenet.UHPlugin.utils.UHUtils; - -import org.bukkit.*; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.*; - -public class UHGameManager { - - private UHPlugin p = null; - private TeamManager tm = null; - private I18n i = null; - private Random random = null; - - private Boolean damageIsOn = false; - - private HashSet<String> players = new HashSet<String>(); // Will be converted to UUID when a built-in API for name->UUID conversion will be available - private HashSet<UUID> alivePlayers = new HashSet<UUID>(); - private HashSet<UHTeam> aliveTeams = new HashSet<UHTeam>(); - private HashSet<UUID> spectators = new HashSet<UUID>(); - private Map<UUID,Location> deathLocations = new HashMap<UUID,Location>(); - - private HashSet<String> deadPlayersToBeResurrected = new HashSet<String>(); // Same - - private Integer alivePlayersCount = 0; - private Integer aliveTeamsCount = 0; - - private Boolean gameWithTeams = true; - - // Used for the slow start. - private Boolean slowStartInProgress = false; - private Boolean slowStartTPFinished = false; - - private Boolean gameStarted = false; - private Boolean gameFinished = false; - private Integer episode = 0; - private UHSound deathSound = null; - - // Used to send a contextual error message in UHCommandManager, using only one exception, - // by checking the message. (Used in this.finishGame().) - public final static String FINISH_ERROR_NOT_STARTED = "Unable to finish the game: the game is not started"; - public final static String FINISH_ERROR_NOT_FINISHED = "Unable to finish the game: the game is not finished"; - - - public UHGameManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - this.tm = p.getTeamManager(); - - this.random = new Random(); - - - // Registers the death sound - this.deathSound = new UHSound(p.getConfig().getConfigurationSection("death.announcements.sound")); - } - - /** - * Initializes the environment before the start of the game. - */ - public void initEnvironment() { - p.getServer().getWorlds().get(0).setGameRuleValue("doDaylightCycle", "false"); - p.getServer().getWorlds().get(0).setTime(6000L); - p.getServer().getWorlds().get(0).setStorm(false); - p.getServer().getWorlds().get(0).setDifficulty(Difficulty.HARD); - } - - /** - * Initializes the given player. - * - * - Teleportation to the default world's spawn point. - * - Max food level & health. - * - Scoreboard. - * - Fixed health score. - * - Spectate mode disabled. - * - Gamemode: creative (if permission "uh.build" granted) or adventure (else). - * - * @param player - */ - public void initPlayer(final Player player) { - - if(p.getConfig().getBoolean("teleportToSpawnIfNotStarted")) { - Location l = player.getWorld().getSpawnLocation().add(0.5, 0.5, 0.5); - if(!UHUtils.safeTP(player, l)) { - player.teleport(l.add(0,1,0)); - } - } - - player.setFoodLevel(20); - player.setSaturation(20f); - player.setHealth(20d); - - p.getScoreboardManager().setScoreboardForPlayer(player); - - // Used to update the "health" objective, to avoid a null one. - // Launched later because else, the health is constantly set to 20, - // and this prevents the health score to be updated. - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - p.getScoreboardManager().updateHealthScore(player); - } - }, 20L); - - // Disable the spectator mode if the game is not started. - if(p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - p.getSpectatorPlusIntegration().getSPAPI().setSpectating(player, false); - } - - // Resets the achievements - if(p.getConfig().getBoolean("achievements.resetAchievementsAtStartup", true)) { - player.removeAchievement(Achievement.OPEN_INVENTORY); - } - - // If the user has the permission to build before the game, he will probably needs - // the creative mode. - if(!player.hasPermission("uh.build")) { - player.setGameMode(GameMode.ADVENTURE); - } - else { - player.setGameMode(GameMode.CREATIVE); - } - } - - - /** - * Starts the game. - * - Teleports the teams - * - Changes the gamemode, reset the life, clear inventories, etc. - * - Launches the timer - * - * @param sender The player who launched the game. - * @param slow If true, the slow mode is enabled. - * With the slow mode, the players are, at first, teleported team by team with a configurable delay, - * and with the fly. - * Then, the fly is removed and the game starts. - * - * @throws IllegalStateException if the game is running. - */ - public void start(CommandSender sender, Boolean slow) throws IllegalStateException { - - if(isGameRunning()) { - throw new IllegalStateException("The game is currently running!"); - } - - p.getMOTDManager().updateMOTDDuringStart(); - - /** Initialization of the players and the teams **/ - - // We adds all the connected players (excepted spectators) to a list of alive players. - // Also, the spectator mode is enabled/disabled if needed. - alivePlayers.clear(); - for(final Player player : p.getServer().getOnlinePlayers()) { - if(!spectators.contains(player.getUniqueId())) { - alivePlayers.add(player.getUniqueId()); - - if(p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - p.getSpectatorPlusIntegration().getSPAPI().setSpectating(player, false); - } - } - else { - if(p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - p.getSpectatorPlusIntegration().getSPAPI().setSpectating(player, true); - } - } - } - - this.alivePlayersCount = alivePlayers.size(); - - // The names of the players is stored for later use - // Used in the resurrectOffline method, to check if a player was really a player or not. - for(UUID id : alivePlayers) { - this.players.add(p.getServer().getPlayer(id).getName()); - } - - // This is used to be able to delete the teams created on-the-fly - ArrayList<String> onTheFlyTeams = new ArrayList<String>(); - boolean useColors = p.getConfig().getBoolean("teams-options.randomColors"); - - - // No team? We creates a team per player. - if(tm.getTeams().isEmpty()) { - this.gameWithTeams = false; - - for(final Player player : p.getServer().getOnlinePlayers()) { - if(!spectators.contains(player.getUniqueId())) { - - String teamName = player.getName(); - teamName = teamName.substring(0, Math.min(teamName.length(), 16)); - - TeamColor color; - if(useColors) color = TeamColor.RANDOM; - else color = null; - - UHTeam team = new UHTeam(teamName, color, this.p); - tm.addTeam(team); - - team.addPlayer(player, true); - } - } - } - // With teams? We adds players without teams to a solo team. - else { - this.gameWithTeams = true; - - for(final Player player : p.getServer().getOnlinePlayers()) { - if(tm.getTeamForPlayer(player) == null && !spectators.contains(player.getUniqueId())) { - - // A team with that name may already exists. - // Tries: - // 1. The name of the player; - // 2. TheName bigRandomNumberHere. - - String teamName = player.getName(); - - if(tm.isTeamRegistered(teamName)) { - // The probability of a conflict here is so small... - // I will not take this possibility into account. - teamName = player.getName() + this.random.nextInt(1000000); - } - - TeamColor color; - if(useColors) color = TeamColor.RANDOM; - else color = null; - - UHTeam team = new UHTeam(teamName, color, this.p); - tm.addTeam(team); - - team.addPlayer(player, true); - - onTheFlyTeams.add(teamName); - } - } - } - - for(UHTeam team : tm.getTeams()) { - if(!team.isEmpty()) aliveTeamsCount++; - } - - if(p.getSpawnsManager().getSpawnPoints().size() < aliveTeamsCount) { - sender.sendMessage(i.t("start.notEnoughTP")); - - // We clears the teams if the game was in solo-mode, to avoid a team-counter to be displayed on the next start - if(!this.gameWithTeams) { - tm.reset(true); - } - // We removes the teams automatically added, to avoid a bad team count. - else { - for(String teamName : onTheFlyTeams) { - tm.removeTeam(teamName, true); - } - } - - aliveTeamsCount = 0; - alivePlayersCount = 0; - return; - } - - /** Teleportation **/ - - // Standard mode - if(slow == false) { - List<Location> unusedTP = p.getSpawnsManager().getSpawnPoints(); - for (final UHTeam t : tm.getTeams()) { - if(t.isEmpty()) continue; - - final Location lo = unusedTP.get(this.random.nextInt(unusedTP.size())); - - BukkitRunnable teamStartTask = new TeamStartTask(p, t, lo); - teamStartTask.runTaskLater(p, 10L); - - unusedTP.remove(lo); - } - - - this.startEnvironment(); - this.startTimer(); - this.scheduleDamages(); - this.sendStartupProTips(); - this.finalizeStart(); - } - - // Slow mode - else { - slowStartInProgress = true; - - // The players are frozen during the start. - p.getFreezer().setGlobalFreezeState(true, false); - - // Used to display the number of teams, players... in the scoreboard instead of 0 - // while the players are teleported. - p.getScoreboardManager().updateCounters(); - - // A simple information, because this start is slower (yeah, Captain Obvious here) - p.getServer().broadcastMessage(i.t("start.teleportationInProgress")); - - - // TP - - List<Location> unusedTP = p.getSpawnsManager().getSpawnPoints(); - Integer teamsTeleported = 1; - Integer delayBetweenTP = p.getConfig().getInt("start.slow.delayBetweenTP"); - - for (UHTeam t : tm.getTeams()) { - if(t.isEmpty()) continue; - - Location lo = unusedTP.get(random.nextInt(unusedTP.size())); - - BukkitRunnable teamStartTask = new TeamStartTask(p, t, lo, true, sender, teamsTeleported); - teamStartTask.runTaskLater(p, 20L * teamsTeleported * delayBetweenTP); - - teamsTeleported++; - - unusedTP.remove(lo); - } - - // The end is handled by this.finalizeStartSlow(). - } - } - - /** - * Finalizes the start of the game, with the slow mode. - * Removes the fly and ends the start (environment, timer...) - * - * @param sender - */ - public void finalizeStartSlow(CommandSender sender) { - - if(!this.slowStartInProgress) { - sender.sendMessage(i.t("start.startSlowBeforeStartSlowGo")); - return; - } - - if(!this.slowStartTPFinished) { - sender.sendMessage(i.t("start.startSlowWaitBeforeGo")); - return; - } - - // The freeze is removed. - p.getFreezer().setGlobalFreezeState(false, false); - - // The fly is removed to everyone - for(Player player : p.getServer().getOnlinePlayers()) { - if(alivePlayers.contains(player.getUniqueId())) { - player.setFlying(false); - player.setAllowFlight(false); - } - } - - // The environment is initialized, the game is started. - this.startEnvironment(); - this.startTimer(); - this.scheduleDamages(); - this.sendStartupProTips(); - this.finalizeStart(); - - this.slowStartInProgress = false; - } - - /** - * Initializes the environment at the beginning of the game. - */ - private void startEnvironment() { - World w = p.getServer().getWorlds().get(0); - - w.setGameRuleValue("doDaylightCycle", ((Boolean) p.getConfig().getBoolean("daylightCycle.do")).toString()); - w.setGameRuleValue("keepInventory", ((Boolean) false).toString()); // Just in case... - - w.setTime(p.getConfig().getLong("daylightCycle.time")); - w.setStorm(false); - w.setDifficulty(Difficulty.HARD); - } - - /** - * Launches the timer by launching the task that updates the scoreboard every second. - */ - private void startTimer() { - if(p.getConfig().getBoolean("episodes.enabled")) { - this.episode = 1; - - // An empty string is used for the name of the main timer, because - // such a name can't be used by players. - UHTimer mainTimer = new UHTimer(""); - mainTimer.setDuration(this.getEpisodeLength()); - - p.getTimerManager().registerMainTimer(mainTimer); - - mainTimer.start(); - } - } - - /** - * Enables the damages 30 seconds (600 ticks) later. - */ - private void scheduleDamages() { - // 30 seconds later, damages are enabled. - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - damageIsOn = true; - } - }, 600L); - } - - /** - * Sends two ProTips: - * - about the team chat, to all players, 20 seconds after the beginning of the game; - * - about the invincibility, 5 seconds after the beginning of the game. - */ - private void sendStartupProTips() { - // Team chat - 20 seconds after - if(this.isGameWithTeams()) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - for(Player player : getOnlineAlivePlayers()) { - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_USE_T_COMMAND); - } - } - }, 400L); - } - - // Invincibility - 5 seconds after - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - for(Player player : getOnlineAlivePlayers()) { - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_STARTUP_INVINCIBILITY); - } - } - }, 100L); - } - - /** - * Changes the state of the game. - * Also, forces the global freeze start to false, to avoid toggle bugs (like inverted state). - */ - private void finalizeStart() { - p.getFreezer().setGlobalFreezeState(false); - - this.gameStarted = true; - this.gameFinished = false; - - updateAliveCache(); - - p.getScoreboardManager().buildSidebar(); - - // Fires the event - p.getServer().getPluginManager().callEvent(new UHGameStartsEvent()); - } - - /** - * Notify the game manager the teleportation is finished. - * - * @param finished True if the TP is finished. - */ - public void setSlowStartTPFinished(Boolean finished) { - this.slowStartTPFinished = finished; - } - - /** - * Returns true if the slow start is in progress. - * - * @return - */ - public boolean isSlowStartInProgress() { - return slowStartInProgress; - } - - /** - * Updates the cached values of the alive players and teams. - */ - public void updateAliveCache() { - // Alive teams - aliveTeams.clear(); - for (UHTeam t : tm.getTeams()) { - for (UUID pid : t.getPlayersUUID()) { - if (!this.isPlayerDead(pid) && !aliveTeams.contains(t)) aliveTeams.add(t); - } - } - - // Counters - this.alivePlayersCount = alivePlayers.size(); - this.aliveTeamsCount = aliveTeams.size(); - - p.getScoreboardManager().updateCounters(); - - p.getMOTDManager().updateMOTDDuringGame(); - } - - /** - * Updates the cached values of the alive players and teams. - * - * @deprecated Use {@link #updateAliveCache()} instead. - */ - @Deprecated - public void updateAliveCounters() { - updateAliveCache(); - } - - - /** - * Shifts an episode. - * - * @param shifter The player who shifts the episode, an empty string if the episode is shifted because the timer is up. - */ - public void shiftEpisode(String shifter) { - if(p.getConfig().getBoolean("episodes.enabled")) { - this.episode++; - - EpisodeChangedCause cause; - if(shifter.equals("")) cause = EpisodeChangedCause.FINISHED; - else cause = EpisodeChangedCause.SHIFTED; - - // Restarts the timer. - // Useless for a normal start (restarted in the event), but needed if the episode was shifted. - if(cause == EpisodeChangedCause.SHIFTED) { - p.getScoreboardManager().restartTimers(); - p.getTimerManager().getMainTimer().start(); - } - - p.getScoreboardManager().updateCounters(); - - p.getServer().getPluginManager().callEvent(new UHEpisodeChangedEvent(episode, cause, shifter)); - } - } - - /** - * Shift an episode because the timer is up. - */ - public void shiftEpisode() { - shiftEpisode(""); - } - - - /** - * Resurrects an offline player. - * The tasks that needed to be executed when the player is online are delayed - * and executed when the player joins. - * - * @param playerName The name of the player to resurrect - * @return true if the player was dead, false otherwise. - */ - public boolean resurrect(String playerName) { - - Player playerOnline = Bukkit.getPlayer(playerName); - - if(playerOnline != null) { - return resurrectPlayerOnlineTask(playerOnline); - } - else { - // We checks if the player was a player - if(!this.players.contains(playerName)) { - return false; - } - } - - // So, now, we are sure that the player is really offline. - // The task needed to be executed will be executed when the player join. - this.deadPlayersToBeResurrected.add(playerName); - - return true; - } - - /** - * The things that have to be done in order to resurrect the players - * and that needs the player to be online. - * - * @param player The player to resurrect - * @return true if the player was dead, false otherwise. - */ - public boolean resurrectPlayerOnlineTask(Player player) { - - if(alivePlayers.contains(player.getUniqueId())) { - return false; - } - - // Player registered as alive - alivePlayers.add(player.getUniqueId()); - updateAliveCache(); - - // This method can be used to add a player after the game start. - if(!players.contains(player.getName())) { - players.add(player.getName()); - } - - // Event - p.getServer().getPluginManager().callEvent(new UHPlayerResurrectedEvent(player)); - - return true; - } - - /** - * Returns true if a player need to be resurrected. - * - * @param player - * @return - */ - public boolean isDeadPlayersToBeResurrected(Player player) { - return deadPlayersToBeResurrected.contains(player.getName()); - } - - /** - * Registers a player as resurrected. - * - * @param player - */ - public void markPlayerAsResurrected(Player player) { - deadPlayersToBeResurrected.remove(player.getName()); - } - - - /** - * This method saves the location of the death of a player. - * - * @param player - * @param location - */ - public void addDeathLocation(Player player, Location location) { - deathLocations.put(player.getUniqueId(), location); - } - - /** - * This method removes the stored death location. - * @param player - */ - public void removeDeathLocation(Player player) { - deathLocations.remove(player.getUniqueId()); - } - - /** - * This method returns the stored death location. - * - * @param player - * @return Location - */ - public Location getDeathLocation(Player player) { - if(deathLocations.containsKey(player.getUniqueId())) { - return deathLocations.get(player.getUniqueId()); - } - - return null; - } - - /** - * This method returns true if a death location is stored for the given player. - * - * @param player - * @return boolean - */ - public boolean hasDeathLocation(Player player) { - return deathLocations.containsKey(player.getUniqueId()); - } - - /** - * Adds a spectator. When the game is started, spectators are ignored - * and the spectator mode is enabled if SpectatorPlus is present. - * - * @param player The player to register as a spectator. - */ - public void addStartupSpectator(Player player) { - spectators.add(player.getUniqueId()); - tm.removePlayerFromTeam(player); - } - - /** - * Removes a spectator. - * - * @param player - */ - public void removeStartupSpectator(Player player) { - spectators.remove(player.getUniqueId()); - } - - /** - * Returns a list of the current registered spectators. - * - * This returns only a list of the <em>initial</em> spectators. - * Use {@link #getAlivePlayers()} to get the alive players, and remove - * the elements of this list from the online players to get the spectators. - * - * @return The initial spectators. - */ - public HashSet<String> getStartupSpectators() { - - HashSet<String> spectatorNames = new HashSet<String>(); - - for(UUID id : spectators) { - spectatorNames.add(p.getServer().getPlayer(id).getName()); - } - - return spectatorNames; - } - - /** - * Returns true if the game was launched and is not finished. - * - * @return The running state. - */ - public boolean isGameRunning() { - return gameStarted && !gameFinished; - } - - /** - * Returns true if the game is started. - * - * @return - */ - public boolean isGameStarted() { - return gameStarted; - } - - /** - * Returns true if the game is finished. - * @return - */ - public boolean isGameFinished() { - return gameFinished; - } - - /** - * Registers the state of the game. - * - * @param finished If true, the game will be marked as finished. - */ - public void setGameFinished(boolean finished) { - gameFinished = finished; - } - - /** - * Returns true if the game is a game with teams, and false if the game is a solo game. - * - * @return - */ - public boolean isGameWithTeams() { - return gameWithTeams; - } - - /** - * Returns true if damages are enabled. - * Damages are enabled 30 seconds after the beginning of the game. - * - * @return - */ - public boolean isTakingDamage() { - return damageIsOn; - } - - /** - * Returns true if the given player is dead. - * - * @param player The player. - * @return True if the player is dead. - */ - public boolean isPlayerDead(Player player) { - return !alivePlayers.contains(player.getUniqueId()); - } - - /** - * Returns true if the given player is dead. - * - * @param player The UUID of the player. - * @return True if the player is dead. - */ - public boolean isPlayerDead(UUID player) { - return !alivePlayers.contains(player); - } - - /** - * Registers a player as dead. - * - * @param player The player to mark as dead. - */ - public void addDead(Player player) { - alivePlayers.remove(player.getUniqueId()); - updateAliveCache(); - } - - /** - * Registers a player as dead. - * - * @param player The UUID of the player to mark as dead. - */ - public void addDead(UUID player) { - alivePlayers.remove(player); - updateAliveCache(); - } - - - /** - * Broadcasts the winner(s) of the game and launches some fireworks - * - * @throws IllegalStateException if the game is not started or not finished - * (use the message to distinguish these cases, {@link #FINISH_ERROR_NOT_STARTED} - * or {@link #FINISH_ERROR_NOT_FINISHED}). - */ - public void finishGame() { - if(!p.getGameManager().isGameStarted()) { - throw new IllegalStateException(FINISH_ERROR_NOT_STARTED); - } - - if(p.getGameManager().getAliveTeamsCount() != 1) { - throw new IllegalStateException(FINISH_ERROR_NOT_FINISHED); - } - - // There's only one team. - p.getLogger().info(p.getGameManager().getAliveTeams().toString()); - UHTeam winnerTeam = p.getGameManager().getAliveTeams().iterator().next(); - Set<OfflinePlayer> listWinners = winnerTeam.getPlayers(); - - if(p.getConfig().getBoolean("finish.message")) { - if(p.getGameManager().isGameWithTeams()) { - String winners = ""; - int j = 0; - - for(OfflinePlayer winner : listWinners) { - if(j == 0) { - // Nothing - } - else if(j == listWinners.size() - 1) { - winners += " " + i.t("finish.and") + " "; - } - else { - winners += ", "; - } - - winners += winner.getName(); - j++; - } - - p.getServer().broadcastMessage(i.t("finish.broadcast.withTeams", winners, winnerTeam.getDisplayName())); - } - else { - p.getServer().broadcastMessage(i.t("finish.broadcast.withoutTeams", winnerTeam.getName())); - } - } - - if(p.getConfig().getBoolean("finish.fireworks.enabled")) { - new FireworksOnWinnersTask(p, listWinners).runTaskTimer(p, 0l, 10l); - } - } - - /** - * Returns a list of the currently alive teams. - * - * @return The list. - */ - public Set<UHTeam> getAliveTeams() { - return aliveTeams; - } - - /** - * Returns a list of the currently alive players. - * - * @return The list. - */ - public Set<OfflinePlayer> getAlivePlayers() { - - HashSet<OfflinePlayer> alivePlayersList = new HashSet<OfflinePlayer>(); - - for(UUID id : alivePlayers) { - alivePlayersList.add(p.getServer().getOfflinePlayer(id)); - } - - return alivePlayersList; - } - - /** - * Returns a list of the currently alive and online players. - * - * @return The list. - */ - public HashSet<Player> getOnlineAlivePlayers() { - - HashSet<Player> alivePlayersList = new HashSet<Player>(); - - for(UUID id : alivePlayers) { - Player player = p.getServer().getPlayer(id); - if(player != null) { - alivePlayersList.add(player); - } - } - - return alivePlayersList; - } - - /** - * Returns the death sound, or null if no death sound is registered. - * - * @return - */ - public UHSound getDeathSound() { - return deathSound; - } - - /** - * Returns the length of one episode, in seconds. - * - * @return - */ - public Integer getEpisodeLength() { - try { - return UHUtils.string2Time(p.getConfig().getString("episodes.length")); - } catch(IllegalArgumentException e) { - return 20 * 60; // default value, 20 minutes - } - } - - /** - * Returns the (cached) number of alive players. - * - * @return - */ - public Integer getAlivePlayersCount() { - return alivePlayersCount; - } - - /** - * Returns the (cached) number of alive teams. - * - * @return - */ - public Integer getAliveTeamsCount() { - return aliveTeamsCount; - } - - /** - * Returns the number of the current episode. - * - * @return - */ - public Integer getEpisode() { - return episode; - } - - - /** - * Adds a spectator. When the game is started, spectators are ignored - * and the spectator mode is enabled if SpectatorPlus is present. - * - * @param player The player to register as a spectator. - * - * @deprecated Use {@link #addStartupSpectator(Player)} instead. - */ - @Deprecated - public void addSpectator(Player player) { - addStartupSpectator(player); - } - - /** - * Removes a spectator. - * - * @param player - * - * @deprecated Use {@link #removeStartupSpectator(Player)} instead. - */ - @Deprecated - public void removeSpectator(Player player) { - removeStartupSpectator(player); - } - - /** - * Returns a list of the current registered spectators. - * - * This returns only a list of the <em>initial</em> spectators. - * Use {@link #getAlivePlayers()} to get the alive players, and remove - * the elements of this list from the online players to get the spectators. - * - * @return The initial spectators. - * - * @deprecated Use {@link #getStartupSpectators()} instead. - */ - @Deprecated - public HashSet<String> getSpectators() { - return getStartupSpectators(); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/UHPlugin.java b/src/main/java/me/azenet/UHPlugin/UHPlugin.java deleted file mode 100644 index 191b07c..0000000 --- a/src/main/java/me/azenet/UHPlugin/UHPlugin.java +++ /dev/null @@ -1,337 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin; - -import me.azenet.UHPlugin.borders.BorderManager; -import me.azenet.UHPlugin.commands.UHCommandExecutor; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.integration.UHDynmapIntegration; -import me.azenet.UHPlugin.integration.UHProtocolLibIntegrationWrapper; -import me.azenet.UHPlugin.integration.UHSpectatorPlusIntegration; -import me.azenet.UHPlugin.integration.UHWorldBorderIntegration; -import me.azenet.UHPlugin.listeners.CraftingListener; -import me.azenet.UHPlugin.listeners.GameListener; -import me.azenet.UHPlugin.listeners.GameplayListener; -import me.azenet.UHPlugin.misc.Freezer; -import me.azenet.UHPlugin.misc.MOTDManager; -import me.azenet.UHPlugin.misc.ProTipsSender; -import me.azenet.UHPlugin.misc.RuntimeCommandsExecutor; -import me.azenet.UHPlugin.recipes.RecipesManager; -import me.azenet.UHPlugin.scoreboard.ScoreboardManager; -import me.azenet.UHPlugin.spawns.SpawnsManager; -import me.azenet.UHPlugin.task.UpdateTimerTask; -import me.azenet.UHPlugin.teams.TeamChatManager; -import me.azenet.UHPlugin.teams.TeamManager; -import me.azenet.UHPlugin.timers.TimerManager; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.mcstats.MetricsLite; - -import java.io.IOException; - -public final class UHPlugin extends JavaPlugin { - - private UHPluginCommand commandManager = null; - private UHTabCompleter tabCompleter = null; - - private TeamManager teamManager = null; - private SpawnsManager spawnsManager = null; - private UHGameManager gameManager = null; - private ScoreboardManager scoreboardManager = null; - private MOTDManager motdManager = null; - private BorderManager borderManager = null; - private RecipesManager recipesManager = null; - private TeamChatManager teamChatManager = null; - private TimerManager timerManager = null; - - private RuntimeCommandsExecutor runtimeCommandsExecutor = null; - - private Freezer freezer = null; - - private ProTipsSender protipsSender = null; - - private UHWorldBorderIntegration wbintegration = null; - private UHSpectatorPlusIntegration spintegration = null; - private UHDynmapIntegration dynmapintegration = null; - private UHProtocolLibIntegrationWrapper protocollibintegrationwrapper = null; - - private I18n i18n = null; - - @Override - public void onEnable() { - this.saveDefaultConfig(); - - if(getConfig().getString("lang") == null) { - i18n = new I18n(this); - } - else { - i18n = new I18n(this, getConfig().getString("lang")); - } - - teamManager = new TeamManager(this); - gameManager = new UHGameManager(this); - spawnsManager = new SpawnsManager(this); - borderManager = new BorderManager(this); - recipesManager = new RecipesManager(this); - teamChatManager = new TeamChatManager(this); - timerManager = new TimerManager(); - - runtimeCommandsExecutor = new RuntimeCommandsExecutor(this); - - freezer = new Freezer(this); - - protipsSender = new ProTipsSender(this); - - scoreboardManager = new ScoreboardManager(this); - motdManager = new MOTDManager(this); - - wbintegration = new UHWorldBorderIntegration(this); - spintegration = new UHSpectatorPlusIntegration(this); - dynmapintegration = new UHDynmapIntegration(this); - - // Needed to avoid a NoClassDefFoundError. - // I don't like this way of doing this, but else, the plugin will not load without ProtocolLib. - protocollibintegrationwrapper = new UHProtocolLibIntegrationWrapper(this); - - /*commandManager = new UHPluginCommand(this); - tabCompleter = new UHTabCompleter(this); - - getCommand("uh").setExecutor(commandManager); - getCommand("t").setExecutor(commandManager); - getCommand("g").setExecutor(commandManager); - getCommand("togglechat").setExecutor(commandManager); - getCommand("join").setExecutor(commandManager); - getCommand("leave").setExecutor(commandManager); - - getCommand("uh").setTabCompleter(tabCompleter); - getCommand("togglechat").setTabCompleter(tabCompleter); - getCommand("join").setTabCompleter(tabCompleter);*/ - - UHCommandExecutor executor = new UHCommandExecutor(this); - for(String commandName : getDescription().getCommands().keySet()) { - getCommand(commandName).setExecutor(executor); - getCommand(commandName).setTabCompleter(executor); - } - - getServer().getPluginManager().registerEvents(new GameListener(this), this); - getServer().getPluginManager().registerEvents(new GameplayListener(this), this); - getServer().getPluginManager().registerEvents(new CraftingListener(this), this); - // The freezer listener is registered by the freezer when it is needed. - - recipesManager.registerRecipes(); - gameManager.initEnvironment(); - - motdManager.updateMOTDBeforeStart(); - - // In case of reload - for(Player player : getServer().getOnlinePlayers()) { - gameManager.initPlayer(player); - } - - // Imports spawnpoints from the config. - this.spawnsManager.importSpawnPointsFromConfig(); - - // Imports teams from the config. - this.teamManager.importTeamsFromConfig(); - - // Starts the task that updates the timers. - // Started here, so a timer can be displayed before the start of the game - // (example: countdown before the start). - new UpdateTimerTask(this).runTaskTimer(this, 20l, 20l); - - // Schedule commands - runtimeCommandsExecutor.registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_SERVER_START); - - // Launch metrics - if(getConfig().getBoolean("metrics")) { - try { - MetricsLite metrics = new MetricsLite(this); - metrics.start(); - } catch (IOException e) { - // Failed to submit the stats :-( - } - } - else { - getLogger().info("Metrics disabled for this plugin in the configuration: nothing was sent."); - } - - getLogger().info(i18n.t("load.loaded")); - } - - /** - * Returns the team manager. - * - * @return - */ - public TeamManager getTeamManager() { - return teamManager; - } - - /** - * Returns the game manager. - * - * @return - */ - public UHGameManager getGameManager() { - return gameManager; - } - - /** - * Returns the scoreboard manager. - * - * @return - */ - public ScoreboardManager getScoreboardManager() { - return scoreboardManager; - } - - /** - * Returns the MOTD manager. - * - * @return - */ - public MOTDManager getMOTDManager() { - return motdManager; - } - - /** - * Returns the spawns points manager. - * - * @return - */ - public SpawnsManager getSpawnsManager() { - return spawnsManager; - } - - /** - * Returns the command manager. - * - * @return - */ - public UHPluginCommand getCommandManager() { - return commandManager; - } - - /** - * Returns the border manager. - * - * @return - */ - public BorderManager getBorderManager() { - return borderManager; - } - - /** - * Returns the recipe manager. - * @return - */ - public RecipesManager getRecipesManager() { - return recipesManager; - } - - /** - * Returns the team-chat manager. - * @return - */ - public TeamChatManager getTeamChatManager() { - return teamChatManager; - } - - /** - * Returns the timer manager. - * @return - */ - public TimerManager getTimerManager() { - return timerManager; - } - - /** - * Returns the manager used to manage the commands executed after the start/the end of the - * game (or any other moment using the generic API). - * @return - */ - public RuntimeCommandsExecutor getRuntimeCommandsExecutor() { - return runtimeCommandsExecutor; - } - - /** - * Returns the freezer. - * - * @return - */ - public Freezer getFreezer() { - return freezer; - } - - /** - * Returns the ProTips sender. - * - * @return - */ - public ProTipsSender getProtipsSender() { - return protipsSender; - } - - /** - * Returns the representation of the WorldBorder integration in the plugin. - * - * @return - */ - public UHWorldBorderIntegration getWorldBorderIntegration() { - return wbintegration; - } - - /** - * Returns the representation of the SpectatorPlus integration in the plugin. - * - * @return - */ - public UHSpectatorPlusIntegration getSpectatorPlusIntegration() { - return spintegration; - } - - /** - * Returns the representation of the dynmap integration in the plugin. - * - * @return - */ - public UHDynmapIntegration getDynmapIntegration() { - return dynmapintegration; - } - - /** - * Returns a wrapper of the representation of the ProtocolLib integration in the plugin. - * - * @return - */ - public UHProtocolLibIntegrationWrapper getProtocolLibIntegrationWrapper() { - return protocollibintegrationwrapper; - } - - - /** - * Returns the internationalization manager. - * - * @return - */ - public I18n getI18n() { - return i18n; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/UHPluginCommand.java b/src/main/java/me/azenet/UHPlugin/UHPluginCommand.java deleted file mode 100644 index 64f2d4c..0000000 --- a/src/main/java/me/azenet/UHPlugin/UHPluginCommand.java +++ /dev/null @@ -1,2445 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin; - -import me.azenet.UHPlugin.borders.MapShape; -import me.azenet.UHPlugin.borders.exceptions.CannotGenerateWallsException; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import me.azenet.UHPlugin.spawns.exceptions.UnknownGeneratorException; -import me.azenet.UHPlugin.teams.TeamColor; -import me.azenet.UHPlugin.teams.TeamManager; -import me.azenet.UHPlugin.teams.UHTeam; -import me.azenet.UHPlugin.timers.UHTimer; -import me.azenet.UHPlugin.utils.UHUtils; -import org.apache.commons.lang.WordUtils; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.command.BlockCommandSender; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.*; -import java.util.Map.Entry; -import java.util.jar.Attributes; -import java.util.jar.Manifest; - -public class UHPluginCommand implements CommandExecutor { - - private UHPlugin p = null; - - private ArrayList<String> commands = new ArrayList<String>(); - private ArrayList<String> teamCommands = new ArrayList<String>(); - private ArrayList<String> spawnsCommands = new ArrayList<String>(); - private ArrayList<String> tpCommands = new ArrayList<String>(); - private ArrayList<String> timersCommands = new ArrayList<String>(); - private ArrayList<String> specCommands = new ArrayList<String>(); - private ArrayList<String> borderCommands = new ArrayList<String>(); - private ArrayList<String> freezeCommands = new ArrayList<String>(); - - private I18n i = null; - - - public UHPluginCommand(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - - commands.add("about"); - commands.add("start"); - commands.add("shift"); - commands.add("team"); - commands.add("spawns"); - commands.add("infos"); - commands.add("generatewalls"); - commands.add("border"); - commands.add("heal"); - commands.add("healall"); - commands.add("feed"); - commands.add("feedall"); - commands.add("freeze"); - commands.add("kill"); - commands.add("resurrect"); - commands.add("tpback"); - commands.add("spec"); - commands.add("finish"); - commands.add("tp"); - commands.add("timers"); - - teamCommands.add("add"); - teamCommands.add("remove"); - teamCommands.add("join"); - teamCommands.add("leave"); - teamCommands.add("list"); - teamCommands.add("reset"); - - spawnsCommands.add("add"); - spawnsCommands.add("generate"); - spawnsCommands.add("remove"); - spawnsCommands.add("list"); - spawnsCommands.add("dump"); - spawnsCommands.add("reset"); - - tpCommands.add("team"); - tpCommands.add("spectators"); - - timersCommands.add("add"); - timersCommands.add("set"); - timersCommands.add("display"); - timersCommands.add("hide"); - timersCommands.add("start"); - timersCommands.add("pause"); - timersCommands.add("resume"); - timersCommands.add("stop"); - timersCommands.add("remove"); - timersCommands.add("list"); - - specCommands.add("add"); - specCommands.add("remove"); - specCommands.add("list"); - - borderCommands.add("current"); - borderCommands.add("set"); - borderCommands.add("warning"); - borderCommands.add("check"); - - freezeCommands.add("all"); - freezeCommands.add("none"); - freezeCommands.add("on"); - freezeCommands.add("off"); - } - - - /** - * Handles a command. - * - * @param sender The sender - * @param command The executed command - * @param label The alias used for this command - * @param args The arguments given to the command - * - * @author Amaury Carrade - */ - @SuppressWarnings("rawtypes") - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - - boolean ourCommand = false; - for(String commandName : p.getDescription().getCommands().keySet()) { - if(commandName.equalsIgnoreCase(command.getName())) { - ourCommand = true; - break; - } - } - - if(!ourCommand) { - return false; - } - - /** Team chat commands **/ - - if(command.getName().equalsIgnoreCase("t")) { - doTeamMessage(sender, command, label, args); - return true; - } - if(command.getName().equalsIgnoreCase("g")) { - doGlobalMessage(sender, command, label, args); - return true; - } - if(command.getName().equalsIgnoreCase("togglechat")) { - doToggleTeamChat(sender, command, label, args); - return true; - } - - /** /join & /leave commands **/ - - if(command.getName().equalsIgnoreCase("join")) { - doJoin(sender, command, label, args); - return true; - } - if(command.getName().equalsIgnoreCase("leave")) { - doLeave(sender, command, label, args); - return true; - } - - - if(args.length == 0) { - help(sender, args, false); - return true; - } - - String subcommandName = args[0].toLowerCase(); - - // First: subcommand existence. - if(!this.commands.contains(subcommandName)) { - try { - Integer.valueOf(subcommandName); - help(sender, args, false); - } catch(NumberFormatException e) { // If the subcommand isn't a number, it's an error. - help(sender, args, true); - } - return true; - } - - // Second: is the sender allowed? - if(!isAllowed(sender, subcommandName)) { - unauthorized(sender, command); - return true; - } - - // Third: instantiation - try { - Class<? extends UHPluginCommand> cl = this.getClass(); - Class[] parametersTypes = new Class[]{CommandSender.class, Command.class, String.class, String[].class}; - - Method doMethod = cl.getDeclaredMethod("do" + WordUtils.capitalize(subcommandName), parametersTypes); - - doMethod.invoke(this, new Object[]{sender, command, label, args}); - - return true; - - } catch (NoSuchMethodException e) { - // Unknown method => unknown subcommand. - help(sender, args, true); - return true; - - } catch(SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - sender.sendMessage(i.t("cmd.errorLoad")); - e.printStackTrace(); - return false; - } - } - - - - /** - * Prints the help. - * - * @param sender - * @param error True if the help is printed because the user typed an unknown command. - */ - private void help(CommandSender sender, String[] args, boolean error) { - if(error) { - sender.sendMessage(i.t("cmd.errorUnknown")); - return; - } - - displaySeparator(sender); - - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - - sender.sendMessage(i.t("cmd.legendHelp")); - - if(!(sender instanceof Player)) { - helpPage(sender, 1); - helpPage(sender, 2); - helpPage(sender, 3); - } - else { - int page = 0; - if(args.length == 0) { - page = 1; - } - else { - page = Integer.valueOf(args[0]) <= 3 ? Integer.valueOf(args[0]) : 3; - } - - helpPage(sender, page); - if(page < 3) sender.sendMessage(i.t("cmd.helpNextPage", String.valueOf(page + 1))); - } - - displaySeparator(sender); - } - - /** - * Prints a page of the help (for the player screen). - * - * @param sender The sender - * @param page The page to print (1 to 3). - */ - private void helpPage(CommandSender sender, int page) { - switch(page) { - case 1: - sender.sendMessage(i.t("cmd.titleGameCmd")); - sender.sendMessage(i.t("cmd.helpStart")); - sender.sendMessage(i.t("cmd.helpStartSlow")); - sender.sendMessage(i.t("cmd.helpShift")); - sender.sendMessage(i.t("cmd.helpTeam")); - sender.sendMessage(i.t("cmd.helpSpawns")); - sender.sendMessage(i.t("cmd.helpSpec")); - sender.sendMessage(i.t("cmd.helpWall")); - sender.sendMessage(i.t("cmd.helpBorder")); - break; - case 2: - sender.sendMessage(i.t("cmd.titleBugCmd")); - sender.sendMessage(i.t("cmd.helpHeal")); - sender.sendMessage(i.t("cmd.helpHealall")); - sender.sendMessage(i.t("cmd.helpFeed")); - sender.sendMessage(i.t("cmd.helpFeedall")); - sender.sendMessage(i.t("cmd.helpKill")); - sender.sendMessage(i.t("cmd.helpResurrect")); - sender.sendMessage(i.t("cmd.helpTpback")); - break; - case 3: - sender.sendMessage(i.t("cmd.titleMiscCmd")); - sender.sendMessage(i.t("cmd.helpFreeze")); - sender.sendMessage(i.t("cmd.helpFinish")); - sender.sendMessage(i.t("cmd.helpTP")); - sender.sendMessage(i.t("cmd.helpTimers")); - sender.sendMessage(i.t("cmd.helpInfos")); - sender.sendMessage(i.t("cmd.helpAbout")); - break; - } - } - - - /** - * This method checks if an user is allowed to send a command. - * - * @param sender - * @param subcommand - * @return boolean The allowance status. - */ - private boolean isAllowed(CommandSender sender, String subcommand) { - if(sender instanceof Player) { - if(sender.isOp()) { - return true; - } - else if(sender.hasPermission("uh." + subcommand)) { - return true; - } - else { - return false; - } - } - - return true; - } - - /** - * This method sends a message to a player who try to use a command without the permission. - * - * @param sender - * @param command - */ - private void unauthorized(CommandSender sender, Command command) { - sender.sendMessage(i.t("cmd.errorUnauthorized")); - } - - - /** - * This command prints some informations about the plugin and the translation. - * - * Usage: /uh about - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doAbout(CommandSender sender, Command command, String label, String[] args) { - if(sender instanceof Player) sender.sendMessage(""); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - - // Authors - - String authors = ""; - List<String> listAuthors = p.getDescription().getAuthors(); - for(String author : listAuthors) { - if(author == listAuthors.get(0)) { - // Nothing - } - else if(author == listAuthors.get(listAuthors.size() - 1)) { - authors += " " + i.t("about.and") + " "; - } - else { - authors += ", "; - } - authors += author; - } - sender.sendMessage(i.t("about.authors", authors)); - - // Build number - - String build = null; - try { - Class<? extends UHPlugin> clazz = p.getClass(); - String className = clazz.getSimpleName() + ".class"; - String classPath = clazz.getResource(className).toString(); - if (classPath.startsWith("jar")) { // Class from JAR - String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + - "/META-INF/MANIFEST.MF"; - Manifest manifest = new Manifest(new URL(manifestPath).openStream()); - Attributes attr = manifest.getMainAttributes(); - - build = attr.getValue("Git-Commit"); - } - } catch (IOException e) { - // Build not available. - } - - if(build != null) { - sender.sendMessage(i.t("about.build.number", build)); - } - else { - sender.sendMessage(i.t("about.build.notAvailable")); - } - - // Translation - - sender.sendMessage(i.t("about.i18n.title")); - sender.sendMessage(i.t("about.i18n.selected", i.getSelectedLanguage(), i.getTranslator(i.getSelectedLanguage()))); - sender.sendMessage(i.t("about.i18n.fallback", i.getDefaultLanguage(), i.getTranslator(i.getDefaultLanguage()))); - sender.sendMessage(i.t("about.license.title")); - sender.sendMessage(i.t("about.license.license")); - } - - /** - * This command starts the game. - * - * Usage: /uh start [slow [go]] - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doStart(CommandSender sender, Command command, String label, String[] args) { - - if(args.length == 1) { // /uh start (standard mode) - try { - p.getGameManager().start(sender, false); - } catch(IllegalStateException e) { - sender.sendMessage(i.t("start.already")); - } catch(Exception e) { - e.printStackTrace(); - } - } - else if(args.length == 2 && args[1].equalsIgnoreCase("slow")) { // /uh start slow - try { - p.getGameManager().start(sender, true); - } catch(IllegalStateException e) { - sender.sendMessage(i.t("start.already")); - } catch(Exception e) { - e.printStackTrace(); - } - } - else if(args.length == 3 && args[1].equalsIgnoreCase("slow") && args[2].equalsIgnoreCase("go")) { // /uh start slow go - p.getGameManager().finalizeStartSlow(sender); - } - else { - sender.sendMessage(i.t("start.syntax")); - } - } - - /** - * This command generates the walls around the map. - * - * Usage: /uh generatewalls - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doGeneratewalls(CommandSender sender, Command command, String label, String[] args) { - sender.sendMessage(i.t("wall.startGen")); - - World world = null; - - if(sender instanceof Player) { - world = ((Player) sender).getWorld(); - } - else if(sender instanceof BlockCommandSender) { - world = ((BlockCommandSender) sender).getBlock().getWorld(); - } - else { - world = p.getServer().getWorlds().get(0); - sender.sendMessage(i.t("wall.consoleDefaultWorld", world.getName())); - } - - try { - p.getBorderManager().generateWalls(world); - - } catch(CannotGenerateWallsException e) { - sender.sendMessage(i.t("wall.error")); - return; - - } catch(Exception e) { - sender.sendMessage(i.t("wall.unknownError")); - e.printStackTrace(); - return; - } - - sender.sendMessage(i.t("wall.done")); - } - - /** - * This command adds a spawn point for a team or a player. - * - * Usage: /uh spawns add (as a player, adds the current location, world included). - * Usage: /uh spawns add <x> <z> (as everyone, adds the specified coordinates in the default world). - * Usage: /uh spawns list (lists the spawn points). - * Usage: /uh spawns generate <circular|grid|random> [size = current size of the map] [distanceMin = 250] [count = number of teams registered] - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doSpawns(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // No subcommand given: doc - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.spawnsHelpTitle")); - sender.sendMessage(i.t("cmd.spawnsHelpAdd")); - sender.sendMessage(i.t("cmd.spawnsHelpAddXZ")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerate")); - sender.sendMessage(i.t("cmd.spawnsHelpList")); - sender.sendMessage(i.t("cmd.spawnsHelpDump")); - sender.sendMessage(i.t("cmd.spawnsHelpRemove")); - sender.sendMessage(i.t("cmd.spawnsHelpReset")); - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("add")) { // /uh spawns add <?> - - // World? - World world; - if(sender instanceof Player) { - world = ((Player) sender).getWorld(); - } - else if(sender instanceof BlockCommandSender) { - world = ((BlockCommandSender) sender).getBlock().getWorld(); - } - else { - world = p.getServer().getWorlds().get(0); - } - - if(args.length == 2) { // /uh spawns add - if(!(sender instanceof Player)) { - sender.sendMessage(i.t("spawns.errorCoords")); - return; - } - else { - Player pl = (Player) sender; // Just a way to avoid casts everywhere. - try { - p.getSpawnsManager().addSpawnPoint(pl.getLocation()); - sender.sendMessage(i.t("spawns.add.added", world.getName(), String.valueOf(pl.getLocation().getBlockX()), String.valueOf(pl.getLocation().getBlockZ()))); - } catch(IllegalArgumentException e) { - sender.sendMessage(i.t("spawns.add.outOfLimits")); - } catch(RuntimeException e) { - sender.sendMessage(i.t("spawns.add.noSafeSpot")); - } - } - } - else if(args.length == 3) { // /uh spawns add <x>: Two coordinates needed! - sender.sendMessage(i.t("spawns.error2Coords")); - } - else { // /uh spawns add <x> <z> - try { - p.getSpawnsManager().addSpawnPoint(world, Double.parseDouble(args[2]), Double.parseDouble(args[3])); - sender.sendMessage(i.t("spawns.add.added", world.getName(), args[2], args[3])); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("spawns.NaN")); - } catch(IllegalArgumentException e) { - sender.sendMessage(i.t("spawns.add.outOfLimits")); - } catch(RuntimeException e) { - sender.sendMessage(i.t("spawns.add.noSafeSpot")); - } - } - } - - else if(subcommand.equalsIgnoreCase("list")) { // /uh spawns list - List<Location> spawnPoints = p.getSpawnsManager().getSpawnPoints(); - - if(spawnPoints.size() == 0) { - sender.sendMessage(i.t("spawns.list.nothing")); - } - else { - sender.sendMessage(i.t("spawns.list.count", String.valueOf(spawnPoints.size()))); - - // We want one list per world - Map<World,List<Location>> spanwsInWorlds = new HashMap<World,List<Location>>(); - for(World world : p.getServer().getWorlds()) { - spanwsInWorlds.put(world, new LinkedList<Location>()); - } - - for(Location spawn : spawnPoints) { - spanwsInWorlds.get(spawn.getWorld()).add(spawn); - } - - for(Entry<World, List<Location>> spanwsInWorld : spanwsInWorlds.entrySet()) { - if(spanwsInWorld.getValue().size() == 0) { - continue; - } - - sender.sendMessage(i.t("spawns.list.world", spanwsInWorld.getKey().getName())); - - String itemDisplay; - if(spanwsInWorld.getKey().getEnvironment() == Environment.NORMAL) { - itemDisplay = "spawns.list.item.overworld"; - } - else if(spanwsInWorld.getKey().getEnvironment() == Environment.NETHER) { - itemDisplay = "spawns.list.item.nether"; - } - else if(spanwsInWorld.getKey().getEnvironment() == Environment.THE_END) { - itemDisplay = "spawns.list.item.end"; - } - else { - itemDisplay = "spawns.list.item.other"; - } - - // Displaying this number of spawn points per line - final Integer spawnsPerLine = 5; - - for(int j = 0; j < Math.ceil(Double.valueOf(spanwsInWorld.getValue().size()) / spawnsPerLine); j++) { - String line = ""; - - for(int k = 0; k < spawnsPerLine; k++) { - if(spawnPoints.size() > j*spawnsPerLine + k) { - line += i.t(itemDisplay, String.valueOf(spanwsInWorld.getValue().get(j*spawnsPerLine + k).getBlockX()), String.valueOf(spanwsInWorld.getValue().get(j*spawnsPerLine + k).getBlockZ())) + " "; - } - } - - sender.sendMessage(line); - } - } - } - } - - else if(subcommand.equalsIgnoreCase("dump")) { // /uh spawns dump - - // We want one list per world - Map<World,List<Location>> spanwsInWorlds = new HashMap<World,List<Location>>(); - for(World world : p.getServer().getWorlds()) { - spanwsInWorlds.put(world, new LinkedList<Location>()); - } - - for(Location spawn : p.getSpawnsManager().getSpawnPoints()) { - spanwsInWorlds.get(spawn.getWorld()).add(spawn); - } - - String dump = ""; - - for(Entry<World, List<Location>> spanwsInWorld : spanwsInWorlds.entrySet()) { - if(spanwsInWorld.getValue().size() == 0) { - continue; - } - - dump += "\n* " + spanwsInWorld.getKey().getName() + "\n"; - - for(Location spawn : spanwsInWorld.getValue()) { - dump += spawn.getBlockX() + "," + spawn.getBlockZ() + "\n"; - } - } - - sender.sendMessage(dump); - } - - else if(subcommand.equalsIgnoreCase("generate")) { // /uh spawns generate - // Usage: /uh spawns generate <circular|squared|random> [size = current size of the map] [distanceMin = 250] [count = number of teams registered] [xCenter = xSpawn] [zCenter = zSpawn] [world = sender's world] - - if(args.length < 3) { // Documentation - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsCmdTitle")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsCmd")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsShapesTitle")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsShapesRandom")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsShapesGrid")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsShapesCircular")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsTitle")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsSize")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsDistanceMin")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsCount")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsCenter")); - sender.sendMessage(i.t("cmd.spawnsHelpGenerateDetailsArgsWorld")); - - displaySeparator(sender); - return; - } - - String generationMethod = args[2]; - - // Default values - Integer size = p.getBorderManager().getCurrentBorderDiameter() - 25; // Avoid spawn points being too close to the border - Integer distanceMinBetweenTwoPoints = 250; - World world = p.getServer().getWorlds().get(0); - Double xCenter = world.getSpawnLocation().getX(); - Double zCenter = world.getSpawnLocation().getZ(); - - Integer spawnsCount = 0; - for(UHTeam team : p.getTeamManager().getTeams()) { - if(!team.isEmpty()) spawnsCount++; - } - - if(args.length < 9) { - if(sender instanceof Player) { - world = ((Player) sender).getWorld(); - } - else if(sender instanceof BlockCommandSender) { - world = ((BlockCommandSender) sender).getBlock().getWorld(); - } - - xCenter = world.getSpawnLocation().getX(); - zCenter = world.getSpawnLocation().getZ(); - } - - // What if the game is in solo, or some players are out of all team? - // Only if the spawn count is not provided of course. Else, we don't care, this count - // will be overwritten. - if(args.length < 6) { - if(spawnsCount == 0) { // Solo mode? - sender.sendMessage(i.t("spawns.assumptions.solo")); - spawnsCount = p.getServer().getOnlinePlayers().size() - p.getGameManager().getStartupSpectators().size(); - } - else { - // Trying to find players without team - int playersWithoutTeam = 0; - for(Player player : p.getServer().getOnlinePlayers()) { - if(p.getTeamManager().getTeamForPlayer(player) == null) { - playersWithoutTeam++; - } - } - - if(playersWithoutTeam != 0) { - sender.sendMessage(i.t("spawns.assumptions.partialSolo")); - spawnsCount += playersWithoutTeam; - } - } - } - - try { - if(args.length >= 4) { // size included - size = Integer.valueOf(args[3]); - - if(args.length >= 5) { // distance minimal included - distanceMinBetweenTwoPoints = Integer.valueOf(args[4]); - - if(args.length >= 6) { // spawn count included - spawnsCount = Integer.valueOf(args[5]); - - if(args.length >= 7) { // xCenter included - xCenter = Double.parseDouble(args[6]); - - if(args.length >= 8) { // zCenter included - zCenter = Double.parseDouble(args[7]); - - if(args.length >= 9) { // world included - World inputWorld = p.getServer().getWorld(args[8]); - - if(inputWorld != null) { - world = inputWorld; - } - else { - sender.sendMessage(i.t("spawns.generate.unknownWorld", args[8])); - return; - } - } - } - } - } - } - } - } catch(NumberFormatException e) { - sender.sendMessage(i.t("spawns.NaN")); - return; - } - - - if(spawnsCount <= 0) { - sender.sendMessage(i.t("spawns.generate.nothingToDo")); - return; - } - - - try { - p.getSpawnsManager().generateSpawnPoints(generationMethod, world, spawnsCount, size, distanceMinBetweenTwoPoints, xCenter, zCenter); - - } catch (UnknownGeneratorException e) { - sender.sendMessage(i.t("spawns.generate.unsupportedMethod", generationMethod)); - return; - - } catch (CannotGenerateSpawnPointsException e) { - sender.sendMessage(i.t("spawns.generate.impossible")); - return; - } - - sender.sendMessage(i.t("spawns.generate.success")); - } - - else if(subcommand.equalsIgnoreCase("remove")) { // /uh spawns remove <x> <z> - if(args.length == 2) { // /uh spawns remove - if(!(sender instanceof Player)) { - sender.sendMessage(i.t("spawns.errorCoords")); - } - else { - Player pl = (Player) sender; // Just a way to avoid casts everywhere. - p.getSpawnsManager().removeSpawnPoint(pl.getLocation(), false); - sender.sendMessage(i.t("spawns.remove.removed", pl.getWorld().getName(), String.valueOf(pl.getLocation().getBlockX()), String.valueOf(pl.getLocation().getBlockZ()))); - } - } - else if(args.length == 3) { // /uh spawns add <x>: Two coordinates needed! - sender.sendMessage(i.t("spawns.error2Coords")); - } - else { // /uh spawns remove <x> <z> - try { - World world; - if(sender instanceof Player) { - world = ((Player) sender).getWorld(); - } - else { - world = p.getServer().getWorlds().get(0); - } - - p.getSpawnsManager().removeSpawnPoint(new Location(world, Double.parseDouble(args[2]), 0, Double.parseDouble(args[3])), true); - sender.sendMessage(i.t("spawns.remove.removed", p.getServer().getWorlds().get(0).getName(), args[2], args[3])); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("spawns.NaN")); - } - } - } - - else if(subcommand.equalsIgnoreCase("reset")) { // /uh spawns reset - p.getSpawnsManager().reset(); - sender.sendMessage(i.t("spawns.reset")); - } - } - } - - /** - * This command is used to manage the teams. - * - * Usage: /uh team (for the doc). - * Usage: /uh team <add|remove|join|leave|list|reset> (see doc for details). - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doTeam(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // No action provided: doc - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.teamHelpTitle")); - sender.sendMessage(i.t("cmd.teamHelpAdd")); - sender.sendMessage(i.t("cmd.teamHelpAddName")); - sender.sendMessage(i.t("cmd.teamHelpRemove")); - sender.sendMessage(i.t("cmd.teamHelpJoin")); - sender.sendMessage(i.t("cmd.teamHelpLeave")); - sender.sendMessage(i.t("cmd.teamHelpList")); - sender.sendMessage(i.t("cmd.teamHelpReset")); - sender.sendMessage(i.t("cmd.teamHelpJoinCmd")); - sender.sendMessage(i.t("cmd.teamHelpLeaveCmd")); - displaySeparator(sender); - } - else { - TeamManager tm = p.getTeamManager(); - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("add")) { - if(args.length == 3) { // /uh team add <color> - - TeamColor color = TeamColor.fromString(args[2]); - UHTeam team; - - if(color == null) { - sender.sendMessage(i.t("team.add.errorColor")); - } - else { - try { - team = tm.addTeam(color); - } - catch(IllegalArgumentException e) { - sender.sendMessage(i.t("team.add.errorExists")); - return; - } - - sender.sendMessage(i.t("team.add.added", team.getDisplayName())); - } - - } - else if(args.length >= 4) { // /uh team add <color> <name ...> - - TeamColor color = TeamColor.fromString(args[2]); - UHTeam team; - - if(color == null) { - sender.sendMessage(i.t("team.add.errorColor")); - } - else { - String name = UHUtils.getStringFromCommandArguments(args, 3); - - try { - team = tm.addTeam(color, name); - } - catch(IllegalArgumentException e) { - e.printStackTrace(); - sender.sendMessage(i.t("team.add.errorExists")); - return; - } - - sender.sendMessage(i.t("team.add.added", team.getDisplayName())); - } - - } - else { - sender.sendMessage(i.t("team.syntaxError")); - } - } - - - else if(subcommand.equalsIgnoreCase("remove")) { - if(args.length >= 3) { // /uh team remove <teamName> - String name = UHUtils.getStringFromCommandArguments(args, 2); - if(!tm.removeTeam(name)) { - sender.sendMessage(i.t("team.remove.doesNotExists")); - } - else { - sender.sendMessage(i.t("team.remove.removed", name)); - } - } - else { - sender.sendMessage(i.t("team.syntaxError")); - } - } - - - else if(subcommand.equalsIgnoreCase("join")) { - if(args.length >= 4) { // /uh team join <player> <teamName> - - OfflinePlayer player = p.getServer().getOfflinePlayer(args[2]); - String teamName = UHUtils.getStringFromCommandArguments(args, 3); - - if(player == null || !player.isOnline()) { - sender.sendMessage(i.t("team.addplayer.disconnected", args[2], teamName)); - } - else { - try { - tm.addPlayerToTeam(teamName, player); - } catch(IllegalArgumentException e) { - sender.sendMessage(i.t("team.addplayer.doesNotExists")); - return; - } - catch(RuntimeException e) { - sender.sendMessage(i.t("team.addplayer.full", teamName)); - return; - } - UHTeam team = p.getTeamManager().getTeam(teamName); - sender.sendMessage(i.t("team.addplayer.success", args[2], team.getDisplayName())); - } - } - else { - sender.sendMessage(i.t("team.syntaxError")); - } - } - - - else if(subcommand.equalsIgnoreCase("leave")) { - if(args.length == 3) { // /uh team leave <player> - - OfflinePlayer player = p.getServer().getOfflinePlayer(args[2]); - - if(player == null) { - sender.sendMessage(i.t("team.removeplayer.disconnected", args[2])); - } - else { - tm.removePlayerFromTeam(player); - sender.sendMessage(i.t("team.removeplayer.success", args[2])); - } - } - else { - sender.sendMessage(i.t("team.syntaxError")); - } - } - - - else if(subcommand.equalsIgnoreCase("list")) { - if(tm.getTeams().size() == 0) { - sender.sendMessage(i.t("team.list.nothing")); - return; - } - - for(final UHTeam team : tm.getTeams()) { - sender.sendMessage(i.t("team.list.itemTeam", team.getDisplayName(), ((Integer) team.getSize()).toString())); - for(final OfflinePlayer player : team.getPlayers()) { - String bullet = null; - if(player.isOnline()) { - bullet = i.t("team.list.bulletPlayerOnline"); - } - else { - bullet = i.t("team.list.bulletPlayerOffline"); - } - - sender.sendMessage(bullet + i.t("team.list.itemPlayer", player.getName())); - } - } - } - - else if(subcommand.equalsIgnoreCase("reset")) { - tm.reset(); - sender.sendMessage(i.t("team.reset.success")); - } - - else { - sender.sendMessage(i.t("team.unknownCommand")); - } - } - } - - - - /** - * This command prints the status of the running game. - * - * Usage: /uh infos - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doInfos(CommandSender sender, Command command, String label, String[] args) { - - displaySeparator(sender); - - if(p.getGameManager().isGameStarted()) { - sender.sendMessage(i.t("infos.players", String.valueOf(p.getGameManager().getAlivePlayersCount()), String.valueOf(p.getGameManager().getAliveTeamsCount()))); - } - else { - sender.sendMessage(i.t("infos.notStarted")); - } - - for(UHTeam team : p.getTeamManager().getTeams()) { - for(OfflinePlayer player : team.getPlayers()) { - if(sender instanceof Player) { - /* We can use a JSON-based message */ - - String json = "{\"text\":\"\",\"extra\":["; - - - // Online/offline bullet - json += "{"; - if(player.isOnline()) { - json += "\"text\":\"" + i.t("infos.bulletOnline") + "\","; - json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("infos.tooltips.online") + "\"}"; - } - else { - json += "\"text\":\"" + i.t("infos.bulletOffline") + "\","; - json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("infos.tooltips.offline") + "\"}"; - } - json += "},"; - - - // Name and team - json += "{"; - json += "\"text\":\"" + team.getColor().toChatColor() + player.getName() + ChatColor.RESET + "\","; - json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("infos.tooltips.team", team.getDisplayName()) + "\"}"; - json += "}"; - - - if(p.getGameManager().isGameStarted()) { - // Separator - json += ",{\"text\":\"" + i.t("infos.separatorAliveState") + "\"},"; - - // Alive state - json += "{"; - if(!p.getGameManager().isPlayerDead(player.getUniqueId())) { - json += "\"text\":\"" + i.t("infos.alive") + "\","; - if(player.isOnline()) { - json += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("infos.tooltips.health", String.valueOf((int) ((Player) player).getHealth())) + "\"}"; - } - } - else { - json += "\"text\":\"" + i.t("infos.dead") + "\""; - } - json += "}"; - } - - - // End - json += "]}"; - - UHUtils.sendJSONMessage((Player) sender, json); - - } else { - /* Fallback to a simple display for the console */ - - String info = null; - - if(player.isOnline()) { - info = i.t("infos.bulletOnline"); - } - else { - info = i.t("infos.bulletOffline"); - } - - info += team.getColor().toChatColor() + player.getName() + ChatColor.RESET; - - if(p.getGameManager().isGameStarted()) { - info += i.t("infos.separatorAliveState"); - - if(!p.getGameManager().isPlayerDead(player.getUniqueId())) { - info += i.t("infos.alive"); - } - else { - info += i.t("infos.dead"); - } - } - - sender.sendMessage(info); - } - } - } - - - displaySeparator(sender); - } - - - - /** - * This command shifts an episode. - * - * Usage: /uh shift (during the game). - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doShift(CommandSender sender, Command command, String label, String[] args) { - if(p.getGameManager().isGameRunning()) { - if(sender instanceof Player) { - p.getGameManager().shiftEpisode((((Player) sender).getName())); - } - else { - p.getGameManager().shiftEpisode(i.t("shift.consoleName")); - } - } - else { - sender.sendMessage(i.t("shift.cantNotStarted")); - } - } - - - /** - * This command heals a player. - * - * Usage: /uh heal <player> <half-hearts> - * - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doHeal(CommandSender sender, Command command, String label, String[] args) { - if(args.length < 2 || args.length > 3) { - sender.sendMessage(i.t("heal.usage")); - return; - } - - Player player = p.getServer().getPlayer(args[1]); - if(player == null || !player.isOnline()) { - sender.sendMessage(i.t("heal.offline")); - return; - } - - double health = 0D; - boolean add = false; // "add" (±, true) or "raw" (exact health, false) mode - - if(args.length == 2) { // /uh heal <player> : full life for player. - health = 20D; - } - else { // /uh heal <player> <hearts> - double diffHealth = 0D; - - try { - if(args[2].startsWith("+")) { - diffHealth = Double.parseDouble(args[2].substring(1)); - add = true; - } - else if(args[2].startsWith("-")) { - diffHealth = -1 * Double.parseDouble(args[2].substring(1)); - add = true; - } - else { - diffHealth = Double.parseDouble(args[2]); - } - } - catch(NumberFormatException e) { - sender.sendMessage(i.t("heal.errorNaN")); - return; - } - - health = !add ? diffHealth : player.getHealth() + diffHealth; - - if(health <= 0D) { - sender.sendMessage(i.t("heal.errorNoKill")); - return; - } - else if(health > 20D) { - health = 20D; - } - } - - player.setHealth(health); - } - - /** - * This command heals all players. - * - * Usage: /uh healall <half-hearts> - * - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doHealall(CommandSender sender, Command command, String label, String[] args) { - double diffHealth = 0D; - double health = 0D; - boolean add = false; // "add" (±, true) or "raw" (exact health, false) mode - - if(args.length == 1) { // /uh healall : full life for all players. - diffHealth = 20D; - } - else { // /uh heal <player> <hearts> - try { - if(args[1].startsWith("+")) { - diffHealth = Double.parseDouble(args[1].substring(1)); - add = true; - } - else if(args[1].startsWith("-")) { - diffHealth = -1 * Double.parseDouble(args[1].substring(1)); - add = true; - } - else { - diffHealth = Double.parseDouble(args[1]); - } - } - catch(NumberFormatException e) { - sender.sendMessage(i.t("heal.errorNaN")); - return; - } - } - - if((!add && diffHealth <= 0) || diffHealth <= -20) { - sender.sendMessage(i.t("heal.allErrorNoKill")); - return; - } - - for(final Player player : p.getServer().getOnlinePlayers()) { - health = !add ? diffHealth : player.getHealth() + diffHealth; - - if(health <= 0D) { - sender.sendMessage(i.t("heal.errorHealthNotUpdatedNoKill", player.getName())); - continue; - } - else if(health > 20D) { - health = 20D; - } - - player.setHealth(health); - } - } - - /** - * This command feeds a player. - * <p> - * Usage: /uh feed <player> [foodLevel=20] [saturation=20] - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doFeed(CommandSender sender, Command command, String label, String[] args) { - if(args.length < 2) { - sender.sendMessage(i.t("feed.usage")); - return; - } - - Player target = p.getServer().getPlayer(args[1]); - if(target == null || !target.isOnline()) { - sender.sendMessage(i.t("feed.offline")); - return; - } - - int foodLevel = 20; - float saturation = 20f; - - if(args.length > 2) { // /uh feed <player> <foodLevel> - try { - foodLevel = Integer.valueOf(args[2]); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("feed.errorNaN")); - return; - } - - if(args.length > 3) { // /uh feed <player> <foodLevel> <saturation> - try { - // The saturation value cannot be more than the food level. - saturation = Math.min(foodLevel, Float.valueOf(args[3])); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("feed.errorNaN")); - return; - } - } - } - - target.setFoodLevel(foodLevel); - target.setSaturation(saturation); - } - - /** - * This command feeds all player. - * <p> - * Usage: /uh feed <player> [foodLevel=20] [saturation=20] - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doFeedall(CommandSender sender, Command command, String label, String[] args) { - - int foodLevel = 20; - float saturation = 20f; - - if(args.length > 1) { // /uh feedall <foodLevel> - try { - foodLevel = Integer.valueOf(args[1]); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("feed.errorNaN")); - return; - } - - if(args.length > 2) { // /uh feedall <foodLevel> <saturation> - try { - // The saturation value cannot be more than the food level. - saturation = Math.min(foodLevel, Float.valueOf(args[2])); - } catch(NumberFormatException e) { - sender.sendMessage(i.t("feed.errorNaN")); - return; - } - } - } - - for(Player player : p.getServer().getOnlinePlayers()) { - player.setFoodLevel(foodLevel); - player.setSaturation(saturation); - } - } - - - /** - * This command marks a player as dead, even if he is offline. - * <p> - * If the player is online, this has the same effect as {@code /kill}. - * <p> - * Usage: /uh kill <player> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doKill(CommandSender sender, Command command, String label, String[] args) { - if(args.length < 2) { - sender.sendMessage(i.t("kill.usage")); - return; - } - - OfflinePlayer player = p.getServer().getOfflinePlayer(args[1]); - - if(player == null) { - sender.sendMessage(i.t("kill.neverPlayed")); - return; - } - - if(!p.getGameManager().isPlayerDead(player.getUniqueId())) { - if(player.isOnline()) { - ((Player) player).setHealth(0); - } - else { - p.getGameManager().addDead(player.getUniqueId()); - } - - sender.sendMessage(i.t("kill.killed", player.getName())); - } - else { - sender.sendMessage(i.t("kill.notAlive", player.getName())); - } - } - - /** - * This command resurrects a player. - * - * Usage: /uh resurrect <player> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doResurrect(CommandSender sender, Command command, String label, String[] args) { - if(args.length != 2) { - sender.sendMessage(i.t("resurrect.usage")); - return; - } - - boolean success = p.getGameManager().resurrect(args[1]); - - Player player = p.getServer().getPlayer(args[1]); - if(player == null || !player.isOnline()) { - if(!success) { // Player does not exists or is nod dead. - sender.sendMessage(i.t("resurrect.unknownOrDead")); - } - else { // Resurrected - sender.sendMessage(i.t("resurrect.offlineOk", args[1])); - } - } - else { - if(!success) { // The player is not dead - sender.sendMessage(i.t("resurrect.notDead", args[1])); - } - } - } - - /** - * This command safely teleports back a player to his death location. - * - * Usage: /uh tpback <player> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doTpback(CommandSender sender, Command command, String label, String[] args) { - if(args.length < 2) { - sender.sendMessage(i.t("tpback.usage")); - return; - } - - Player player = p.getServer().getPlayer(args[1]); - if(player == null || !player.isOnline()) { - sender.sendMessage(i.t("tpback.offline", args[1])); - return; - } - else if(!p.getGameManager().hasDeathLocation(player)) { - sender.sendMessage(i.t("tpback.noDeathLocation", args[1])); - return; - } - - - Location deathLocation = p.getGameManager().getDeathLocation(player); - - if(args.length >= 3 && args[2].equalsIgnoreCase("force")) { - UHUtils.safeTP(player, deathLocation, true); - sender.sendMessage(i.t("tpback.teleported", args[1])); - p.getGameManager().removeDeathLocation(player); - } - else if(UHUtils.safeTP(player, deathLocation)) { - sender.sendMessage(i.t("tpback.teleported", args[1])); - p.getGameManager().removeDeathLocation(player); - } - else { - sender.sendMessage(i.t("tpback.notTeleportedNoSafeSpot", args[1])); - sender.sendMessage(i.t("tpback.notTeleportedNoSafeSpotCmd", args[1])); - } - } - - - /** - * This command manages startup spectators (aka ignored players). - * - * Usage: /uh spec (doc) - * Usage: /uh spec <add|remove|list> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doSpec(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // /uh spec - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - - sender.sendMessage(i.t("cmd.legendHelp")); - if(!p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - sender.sendMessage(i.t("cmd.specHelpNoticeSpectatorPlusNotInstalled")); - } - - sender.sendMessage(i.t("cmd.specHelpTitle")); - sender.sendMessage(i.t("cmd.specHelpAdd")); - sender.sendMessage(i.t("cmd.specHelpRemove")); - sender.sendMessage(i.t("cmd.specHelpList")); - - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("add")) { - if(args.length == 2) { // /uh spec add - sender.sendMessage(i.t("spectators.syntaxError")); - } - else { // /uh spec add <player> - Player newSpectator = p.getServer().getPlayer(args[2]); - if(newSpectator == null) { - sender.sendMessage(i.t("spectators.offline", args[2])); - } - else { - p.getGameManager().addStartupSpectator(newSpectator); - sender.sendMessage(i.t("spectators.add.success", args[2])); - } - } - } - - else if(subcommand.equalsIgnoreCase("remove")) { - if(args.length == 2) { // /uh spec remove - sender.sendMessage(i.t("spectators.syntaxError")); - } - else { // /uh spec remove <player> - Player oldSpectator = p.getServer().getPlayer(args[2]); - if(oldSpectator == null) { - sender.sendMessage(i.t("spectators.offline", args[2])); - } - else { - p.getGameManager().removeStartupSpectator(oldSpectator); - sender.sendMessage(i.t("spectators.remove.success", args[2])); - } - } - } - - else if(subcommand.equalsIgnoreCase("list")) { - HashSet<String> spectators = p.getGameManager().getStartupSpectators(); - if(spectators.size() == 0) { - sender.sendMessage(i.t("spectators.list.nothing")); - } - else { - sender.sendMessage(i.t("spectators.list.countSpectators", String.valueOf(spectators.size()))); - sender.sendMessage(i.t("spectators.list.countOnlyInitial")); - for(String spectator : spectators) { - sender.sendMessage(i.t("spectators.list.itemSpec", spectator)); - } - } - } - } - } - - - /** - * This command manages borders (gets current, checks if players are out, sets a new size, warnings players - * about the future size). - * - * Usage: /uh border (doc) - * Usage: /uh border <current|set [force]|warning|check> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doBorder(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // /uh border - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.borderHelpTitle")); - sender.sendMessage(i.t("cmd.borderHelpCurrent")); - sender.sendMessage(i.t("cmd.borderHelpSet")); - sender.sendMessage(i.t("cmd.borderHelpWarning")); - sender.sendMessage(i.t("cmd.borderHelpWarningCancel")); - sender.sendMessage(i.t("cmd.borderHelpCheck")); - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("current")) { // /uh border current - if(p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - sender.sendMessage(i.t("borders.current.messageCircular", String.valueOf(p.getBorderManager().getCurrentBorderDiameter()))); - } - else { - sender.sendMessage(i.t("borders.current.messageSquared", String.valueOf(p.getBorderManager().getCurrentBorderDiameter()))); - } - } - - else if(subcommand.equalsIgnoreCase("set")) { // /uh border set - if(args.length == 2) { // /uh border set - sender.sendMessage(i.t("borders.syntaxError")); - } - else if(args.length == 3) { // /uh border set <?> - try { - Integer newDiameter = Integer.valueOf(args[2]); - - if(p.getBorderManager().getPlayersOutside(newDiameter).size() != 0) { // Some players are outside - sender.sendMessage(i.t("borders.set.playersOutsideCanceled")); - sender.sendMessage(i.t("borders.set.playersOutsideCanceledCmd", args[2])); - if(!p.getWorldBorderIntegration().isWBIntegrationEnabled()) { - sender.sendMessage(i.t("borders.set.playersOutsideCanceledWarnWorldBorder")); - } - p.getBorderManager().sendCheckMessage(sender, newDiameter); - } - else { - p.getBorderManager().setCurrentBorderDiameter(newDiameter); - - if(p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - p.getServer().broadcastMessage(i.t("borders.set.broadcastCircular", args[2])); - } - else { - p.getServer().broadcastMessage(i.t("borders.set.broadcastSquared", args[2])); - } - } - - } catch(NumberFormatException e) { - sender.sendMessage(i.t("borders.NaN", args[2])); - } - } - else if(args.length == 4 && args[3].equalsIgnoreCase("force")) { // /uh border set <?> force - try { - Integer newDiameter = Integer.valueOf(args[2]); - - p.getBorderManager().setCurrentBorderDiameter(newDiameter); - - if(p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - p.getServer().broadcastMessage(i.t("borders.set.broadcastCircular", args[2])); - } - else { - p.getServer().broadcastMessage(i.t("borders.set.broadcastSquared", args[2])); - } - - } catch(NumberFormatException e) { - sender.sendMessage(i.t("borders.NaN", args[2])); - } - } - } - - else if(subcommand.equalsIgnoreCase("warning")) { // /uh border warning - if(args.length == 2) { // /uh border warning - sender.sendMessage(i.t("borders.syntaxError")); - } - else if(args[2].equalsIgnoreCase("cancel")) { // /uh border warning cancel - p.getBorderManager().cancelWarning(); - sender.sendMessage(i.t("borders.warning.canceled")); - } - else { // /uh border warning <?> - try { - Integer warnDiameter = Integer.valueOf(args[2]); - - Integer warnTime = 0; - if(args.length >= 4) { // /uh border warning <?> <?> - warnTime = Integer.valueOf(args[3]); - } - - p.getBorderManager().setWarningSize(warnDiameter, warnTime, sender); - sender.sendMessage(i.t("borders.warning.set", p.getConfig().getString("map.border.warningInterval", "90"))); - - } catch(NumberFormatException e) { - sender.sendMessage(i.t("borders.NaN", args[2])); - } - } - } - else if(subcommand.equalsIgnoreCase("check")) { - if(args.length == 2) { // /uh border check - sender.sendMessage(i.t("borders.syntaxError")); - } - else { // /uh border check <?> - try { - - Integer checkDiameter = Integer.valueOf(args[2]); - p.getBorderManager().sendCheckMessage(sender, checkDiameter); - - } catch(NumberFormatException e) { - sender.sendMessage(i.t("borders.NaN", args[2])); - } - } - } - } - } - - - /** - * This commands broadcast the winner(s) of the game and sends some fireworks at these players. - * It fails if there is more than one team alive. - * - * Usage: /uh finish - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doFinish(CommandSender sender, Command command, String label, String[] args) { - - try { - p.getGameManager().finishGame(); - - } catch(IllegalStateException e) { - - if(e.getMessage().equals(UHGameManager.FINISH_ERROR_NOT_STARTED)) { - sender.sendMessage(i.t("finish.notStarted")); - } - else if(e.getMessage().equals(UHGameManager.FINISH_ERROR_NOT_FINISHED)) { - sender.sendMessage(i.t("finish.notFinished")); - } - else { - throw e; - } - } - - } - - /** - * This command teleports a team or the spectators to a given location. - * - * Usage: /uh tp team <x> <y> <z> <team name ...> - * Usage: /uh tp team <target> <team name...> - * Usage: /uh tp spectators <x> <y> <z> - * Usage: /uh tp spectators <target> - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doTp(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // No action provided: doc - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.tpHelpTitle")); - sender.sendMessage(i.t("cmd.tpHelpTeam")); - sender.sendMessage(i.t("cmd.tpHelpSpectators")); - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - World targetWorld = null; - if(sender instanceof Player) { - targetWorld = ((Player) sender).getWorld(); - } - else if(sender instanceof BlockCommandSender) { - targetWorld = ((BlockCommandSender) sender).getBlock().getWorld(); - } - else { - targetWorld = p.getServer().getWorlds().get(0); - } - - if(subcommand.equalsIgnoreCase("team")) { - boolean mayBeNaNError = false; - - if(args.length >= 6) { // possibly /uh tp team <x> <y> <z> <team ...> - String teamName = UHUtils.getStringFromCommandArguments(args, 5); - UHTeam team = p.getTeamManager().getTeam(teamName); - - if(team != null) { // ok, the team exists. - try { - double x = Integer.parseInt(args[2]) + 0.5; - double y = Integer.parseInt(args[3]) + 0.5; - double z = Integer.parseInt(args[4]) + 0.5; - - team.teleportTo(new Location(targetWorld, x, y, z)); - - return; - } catch(NumberFormatException e) { - // It can be either another name for the team, starting by "<y> <z> the name" - // or a formatting error. - // The possibility of an error is saved. - mayBeNaNError = true; - } - } - } - if(args.length >= 4) { // /uh tp team <target> <team ...> - String teamName = UHUtils.getStringFromCommandArguments(args, 3); - UHTeam team = p.getTeamManager().getTeam(teamName); - - if(team == null) { - if(mayBeNaNError) { - sender.sendMessage(i.t("tp.NaN")); - } - else { - sender.sendMessage(i.t("tp.teamDoesNotExists")); - } - } - else { - Player target = p.getServer().getPlayer(args[2]); - - if(target == null) { - sender.sendMessage(i.t("tp.targetOffline", args[2])); - } - else { - team.teleportTo(target.getLocation()); - } - } - } - } - else if(subcommand.equalsIgnoreCase("spectators")) { - if(args.length == 5) { // /uh tp spectators <x> <y> <z> - try { - double x = Integer.parseInt(args[2]) + 0.5; - double y = Integer.parseInt(args[3]) + 0.5; - double z = Integer.parseInt(args[4]) + 0.5; - - for(Player player : p.getServer().getOnlinePlayers()) { - if(p.getGameManager().isPlayerDead(player)) { - player.teleport(new Location(targetWorld, x, y, z), TeleportCause.PLUGIN); - } - } - } catch(NumberFormatException e) { - sender.sendMessage(i.t("tp.NaN")); - return; - } - } - else if(args.length == 3) { // /uh tp spectators <target> - Player target = p.getServer().getPlayer(args[2]); - - if(target == null) { - sender.sendMessage(i.t("tp.targetOffline", args[2])); - } - else { - for(Player player : p.getServer().getOnlinePlayers()) { - if(p.getGameManager().isPlayerDead(player)) { - player.teleport(target.getLocation(), TeleportCause.PLUGIN); - } - } - } - } - } - } - } - - - /** - * This command manages timers. - * - * Usage: /uh timers < add | set | display | hide | start | pause | resume | stop | remove | list > - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doTimers(CommandSender sender, Command command, String label, String[] args) throws NumberFormatException { - if(args.length == 1) { // No action provided: doc - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.timersHelpTitle")); - sender.sendMessage(i.t("cmd.timersHelpAdd")); - sender.sendMessage(i.t("cmd.timersHelpSet")); - sender.sendMessage(i.t("cmd.timersHelpDisplay")); - sender.sendMessage(i.t("cmd.timersHelpHide")); - sender.sendMessage(i.t("cmd.timersHelpStart")); - sender.sendMessage(i.t("cmd.timersHelpPause")); - sender.sendMessage(i.t("cmd.timersHelpResume")); - sender.sendMessage(i.t("cmd.timersHelpStop")); - sender.sendMessage(i.t("cmd.timersHelpRemove")); - sender.sendMessage(i.t("cmd.timersHelpList")); - sender.sendMessage(i.t("cmd.timersHelpDurations")); - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("add")) { // /uh timers add <duration> <name ...> - if(args.length < 4) { - sender.sendMessage(i.t("timers.syntaxError")); - } - else { - try { - Integer duration = UHUtils.string2Time(args[2]); - String timerName = UHUtils.getStringFromCommandArguments(args, 3); - - if(p.getTimerManager().getTimer(timerName) != null) { - sender.sendMessage(i.t("timers.alreadyExists", timerName)); - return; - } - - UHTimer timer = new UHTimer(timerName); - timer.setDuration(duration); - - p.getTimerManager().registerTimer(timer); - sender.sendMessage(i.t("timers.added", timer.getDisplayName(), args[2])); - - } catch(IllegalArgumentException e) { - sender.sendMessage(i.t("timers.durationSyntaxError")); - } - } - } - - else if(subcommand.equalsIgnoreCase("set")) { // /uh timers set <duration> <name ...> - if(args.length < 4) { - sender.sendMessage(i.t("timers.syntaxError")); - } - else { - try { - Integer duration = UHUtils.string2Time(args[2]); - String timerName = UHUtils.getStringFromCommandArguments(args, 3); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - timer.setDuration(duration); - sender.sendMessage(i.t("timers.set", timer.getDisplayName(), args[2])); - - } catch(IllegalArgumentException e) { - sender.sendMessage(i.t("timers.durationSyntaxError")); - } - } - } - - else if(subcommand.equalsIgnoreCase("display")) { // /uh timers display <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - p.getScoreboardManager().displayTimer(timer); - sender.sendMessage(i.t("timers.displayed", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("hide")) { // /uh timers hide <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - p.getScoreboardManager().hideTimer(timer); - sender.sendMessage(i.t("timers.hidden", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("start")) { // /uh timers start <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - if(timer.isRunning()) { - timer.stop(); - } - - timer.start(); - sender.sendMessage(i.t("timers.started", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("pause")) { // /uh timers pause <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - timer.setPaused(true); - sender.sendMessage(i.t("timers.paused", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("resume")) { // /uh timers resume <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - timer.setPaused(false); - sender.sendMessage(i.t("timers.resumed", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("stop")) { // /uh timers stop <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - timer.stop(); - sender.sendMessage(i.t("timers.stopped", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("remove")) { // /uh timers remove <name ...> - String timerName = UHUtils.getStringFromCommandArguments(args, 2); - - UHTimer timer = p.getTimerManager().getTimer(timerName); - if(timer == null) { - sender.sendMessage(i.t("timers.timerDoesNotExists")); - return; - } - - p.getScoreboardManager().hideTimer(timer); - p.getTimerManager().unregisterTimer(timer); - timer.stop(); - - sender.sendMessage(i.t("timers.removed", timer.getDisplayName())); - } - - else if(subcommand.equalsIgnoreCase("list")) { // /uh timers list - Collection<UHTimer> timers = p.getTimerManager().getTimers(); - - sender.sendMessage(i.t("timers.list.count", String.valueOf(timers.size()))); - - for(UHTimer timer : timers) { - if(timer.isRunning()) { - if(timer.isPaused()) { - sender.sendMessage(i.t("timers.list.itemPaused", - timer.getDisplayName(), - String.valueOf(timer.getDuration()), - p.getScoreboardManager().getTimerText(timer, false, false))); - } - else { - sender.sendMessage(i.t("timers.list.itemRunning", - timer.getDisplayName(), - String.valueOf(timer.getDuration()), - p.getScoreboardManager().getTimerText(timer, false, false))); - - } - } - else { - sender.sendMessage(i.t("timers.list.itemStopped", - timer.getDisplayName(), - String.valueOf(timer.getDuration()))); - } - } - } - - else { - sender.sendMessage(i.t("timers.syntaxError")); - } - } - } - - - /** - * This command freezes the players. - * - * Usage: /uh freeze <on [player]|off [player]|all|none> - * - on [player]: freezes the given player, or the sender if no player was provided. - * - off [player]: unfreezes the given player (or the sender, same condition). - * - all: freezes all the alive players, the mobs and the timer. - * - none: unfreezes all the alive players (even if there where frozen before using - * /uh freeze all), the mobs and the timer. - * - * @param sender - * @param command - * @param label - * @param args - */ - @SuppressWarnings("unused") - private void doFreeze(CommandSender sender, Command command, String label, String[] args) { - if(args.length == 1) { // /uh freeze - displaySeparator(sender); - sender.sendMessage(i.t("cmd.titleHelp", p.getDescription().getDescription(), p.getDescription().getVersion())); - sender.sendMessage(i.t("cmd.legendHelp")); - - sender.sendMessage(i.t("cmd.freezeHelpTitle")); - sender.sendMessage(i.t("cmd.freezeHelpOn")); - sender.sendMessage(i.t("cmd.freezeHelpOff")); - sender.sendMessage(i.t("cmd.freezeHelpAll")); - sender.sendMessage(i.t("cmd.freezeHelpNone")); - displaySeparator(sender); - } - else { - String subcommand = args[1]; - - if(subcommand.equalsIgnoreCase("on") || subcommand.equalsIgnoreCase("off")) { - - boolean on = subcommand.equalsIgnoreCase("on"); - - if(args.length == 2) { // /uh freeze on: freezes the sender - if(sender instanceof Player) { - p.getFreezer().setPlayerFreezeState((Player) sender, on); - if(on) { - sender.sendMessage(i.t("freeze.frozen", ((Player) sender).getName())); - } - else { - sender.sendMessage(i.t("freeze.unfrozen", ((Player) sender).getName())); - } - } - else { - sender.sendMessage(i.t("freeze.playerOnly")); - } - } - else if(args.length == 3) { // /uh freeze on <player>: freezes <player>. - Player player = p.getServer().getPlayer(args[2]); - if(player == null) { - sender.sendMessage(i.t("freeze.offline", args[2])); - } - else { - p.getFreezer().setPlayerFreezeState(player, on); - if(on) { - player.sendMessage(i.t("freeze.frozen", ((Player) sender).getName())); - sender.sendMessage(i.t("freeze.playerFrozen", player.getName())); - } - else { - player.sendMessage(i.t("freeze.unfrozen", ((Player) sender).getName())); - sender.sendMessage(i.t("freeze.playerUnfrozen", player.getName())); - } - } - } - } - - else if(subcommand.equalsIgnoreCase("all") || subcommand.equalsIgnoreCase("none")) { - - boolean on = subcommand.equalsIgnoreCase("all"); - - p.getFreezer().setGlobalFreezeState(on); - - if(on) { - p.getServer().broadcastMessage(i.t("freeze.broadcast.globalFreeze")); - } - else { - p.getServer().broadcastMessage(i.t("freeze.broadcast.globalUnfreeze")); - } - - } - } - } - - - - - /** - * This command, /t <message>, is used to send a team-message. - * - * @param sender - * @param command - * @param label - * @param args - */ - private void doTeamMessage(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) { - sender.sendMessage(i.t("team.message.noConsole")); - return; - } - - if(args.length == 0) { // /t - sender.sendMessage(i.t("team.message.usage", "t")); - return; - } - - String message = ""; - for(Integer i = 0; i < args.length; i++) { - message += args[i] + " "; - } - - p.getTeamChatManager().sendTeamMessage((Player) sender, message); - } - - /** - * This command, /g <message>, is used to send a global message. - * - * @param sender - * @param command - * @param label - * @param args - */ - private void doGlobalMessage(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) { - sender.sendMessage(i.t("team.message.noConsole")); - return; - } - - if(args.length == 0) { // /g - sender.sendMessage(i.t("team.message.usage", "g")); - return; - } - - String message = ""; - for(Integer i = 0; i < args.length; i++) { - message += args[i] + " "; - } - - p.getTeamChatManager().sendGlobalMessage((Player) sender, message); - } - - /** - * This command, /togglechat, is used to toggle the chat between the global chat and the team chat. - * - * @param sender - * @param command - * @param label - * @param args - */ - private void doToggleTeamChat(CommandSender sender, Command command, String label, String[] args) { - if(!(sender instanceof Player)) { - sender.sendMessage(i.t("team.message.noConsole")); - return; - } - - if(args.length == 0) { // /togglechat - if(p.getTeamChatManager().toggleChatForPlayer((Player) sender)) { - sender.sendMessage(i.t("team.message.toggle.nowTeamChat")); - } - else { - sender.sendMessage(i.t("team.message.toggle.nowGlobalChat")); - } - } - else { // /togglechat <another team> - String teamName = UHUtils.getStringFromCommandArguments(args, 0); - UHTeam team = p.getTeamManager().getTeam(teamName); - - if(team != null) { - if(p.getTeamChatManager().toggleChatForPlayer((Player) sender, team)) { - sender.sendMessage(i.t("team.message.toggle.nowOtherTeamChat", team.getDisplayName())); - } - } - else { - sender.sendMessage(i.t("team.message.toggle.unknownTeam")); - } - } - } - - - - /** - * This command is used to allow a player to join a team. - * <p> - * Usage: /join [player] <team> - * - * @param sender - * @param command - * @param label - * @param args - */ - private void doJoin(CommandSender sender, Command command, String label, String[] args) { - - if(args.length == 0) { - if(sender instanceof Player) { - if(sender.hasPermission("uh.player.join.self")) { - p.getTeamManager().displayTeamChooserChatGUI((Player) sender); - } - else { - if(sender.hasPermission("uh.player.join.others")) { - sender.sendMessage(i.t("team.addplayer.joinhelp")); - } - else { - unauthorized(sender, command); - } - } - } - else { - sender.sendMessage(i.t("team.addplayer.joinhelp")); - } - - return; - } - - UHTeam team = null; - Player target = null; - Boolean self = null; - - // /join <team>? - team = p.getTeamManager().getTeam(UHUtils.getStringFromCommandArguments(args, 0)); - if(team != null) { - if(sender instanceof Player) { - target = (Player) sender; - self = true; - } - else { - sender.sendMessage(i.t("team.onlyAsAPlayer")); - return; - } - } - else if(args.length >= 2) { - // /join <player> <team>? - team = p.getTeamManager().getTeam(UHUtils.getStringFromCommandArguments(args, 1)); - if(team != null) { - target = p.getServer().getPlayer(args[0]); - self = false; - if(target == null) { - sender.sendMessage(i.t("team.addplayer.disconnected", args[0], team.getName())); - return; - } - } - } - - if(team == null) { - sender.sendMessage(i.t("team.addplayer.doesNotExists")); - } - else { - if((self && sender.hasPermission("uh.player.join.self")) - || (!self && sender.hasPermission("uh.player.join.others"))) { - team.addPlayer(target); - - if(!sender.equals(target)) { - sender.sendMessage(i.t("team.addplayer.success", target.getName(), team.getName())); - } - } - else { - unauthorized(sender, command); - } - } - } - - /** - * This command is used to allow a player to quit his team. - * - * @param sender - * @param command - * @param label - * @param args - */ - private void doLeave(CommandSender sender, Command command, String label, String[] args) { - - OfflinePlayer target = null; - - if(args.length >= 1 && sender.hasPermission("uh.player.leave.others")) { - if((target = p.getServer().getOfflinePlayer(args[0])) == null) { - sender.sendMessage(i.t("team.removeplayer.disconnected", args[0])); - return; - } - } - else if(args.length == 0 && sender.hasPermission("uh.player.leave.self")) { - if(sender instanceof Player) { - target = (Player) sender; - } - else { - sender.sendMessage(i.t("team.onlyAsAPlayer")); - return; - } - } - else { - sender.sendMessage(i.t("cmd.errorUnauthorized")); - return; - } - - p.getTeamManager().removePlayerFromTeam(target); - - if(!target.equals(sender)) { - sender.sendMessage(i.t("team.removeplayer.success", args[0])); - } - } - - - - /** - * Displays a separator around the output of the commands. - * <p> - * To be called before and after the output (prints a line only). - * - * @param sender The line will be displayed for this sender. - */ - private void displaySeparator(CommandSender sender) { - if(!(sender instanceof Player)) { - return; - } - - sender.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); - } - - - - public ArrayList<String> getCommands() { - return commands; - } - - public ArrayList<String> getTeamCommands() { - return teamCommands; - } - - public ArrayList<String> getSpawnsCommands() { - return spawnsCommands; - } - - public ArrayList<String> getTPCommands() { - return tpCommands; - } - - public ArrayList<String> getTimersCommands() { - return timersCommands; - } - - public ArrayList<String> getSpecCommands() { - return specCommands; - } - - public ArrayList<String> getBorderCommands() { - return borderCommands; - } - - public ArrayList<String> getFreezeCommands() { - return freezeCommands; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/UHTabCompleter.java b/src/main/java/me/azenet/UHPlugin/UHTabCompleter.java deleted file mode 100644 index 0f306fb..0000000 --- a/src/main/java/me/azenet/UHPlugin/UHTabCompleter.java +++ /dev/null @@ -1,402 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin; - -import me.azenet.UHPlugin.teams.UHTeam; -import me.azenet.UHPlugin.timers.UHTimer; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.OfflinePlayer; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.bukkit.entity.Player; - -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class UHTabCompleter implements TabCompleter { - - private UHPlugin p = null; - - private ArrayList<String> colors = new ArrayList<String>(); - - - public UHTabCompleter(UHPlugin plugin) { - this.p = plugin; - - this.colors.add("aqua"); - this.colors.add("black"); - this.colors.add("blue"); - this.colors.add("darkaqua"); - this.colors.add("darkblue"); - this.colors.add("darkgray"); - this.colors.add("darkgreen"); - this.colors.add("darkpurple"); - this.colors.add("darkred"); - this.colors.add("gold"); - this.colors.add("gray"); - this.colors.add("green"); - this.colors.add("lightpurple"); - this.colors.add("red"); - this.colors.add("white"); - this.colors.add("yellow"); - this.colors.add("?"); - } - - @Override - public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - if (!command.getName().equalsIgnoreCase("uh") - && !command.getName().equalsIgnoreCase("togglechat") - && !command.getName().equalsIgnoreCase("join")) { - return null; - } - - /** ** Autocompletion for the /togglechat command ** **/ - - if(command.getName().equalsIgnoreCase("togglechat")) { - if(sender instanceof Player && ((Player) sender).hasPermission("uh.teamchat.others")) { - ArrayList<String> teamNames = new ArrayList<String>(); - for(UHTeam team : p.getTeamManager().getTeams()) { - teamNames.add(team.getName()); - } - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); - } - return null; - } - - /** ** Autocompletion for the /join command ** **/ - - if(command.getName().equalsIgnoreCase("join")) { - if(sender.hasPermission("uh.player.join.self") || sender.hasPermission("uh.player.join.others")) { - ArrayList<String> teamNames = new ArrayList<String>(); - for(UHTeam team : p.getTeamManager().getTeams()) { - teamNames.add(team.getName()); - } - - // /join <team> - if(args.length == 1 || (args.length > 1 && p.getServer().getPlayer(args[0]) == null)) { - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 0), teamNames, args.length - 1); - } - // /join <player> <team> - else if(args.length > 1) { - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 1), teamNames, args.length - 2); - } - } - } - - - /** ** Autocompletion for the /uh command ** **/ - - /** Autocompletion for subcommands **/ - if(args.length == 1) { - return getAutocompleteSuggestions(args[0], p.getCommandManager().getCommands()); - } - - /** Autocompletion for /uh team **/ - // The player names autocomplete is handled by Bukkit. - if(args[0].equalsIgnoreCase("team")) { - - // /uh team <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getTeamCommands()); - } - - // /uh team subcommand <?> - else if(args.length == 3) { - - if(args[1].equalsIgnoreCase("add")) { // Autocompletion for colors - return getAutocompleteSuggestions(args[2], this.colors); - } - else if(args[1].equalsIgnoreCase("remove")) { // Autocompletion for teams names - ArrayList<String> teamNames = new ArrayList<String>(); - for(UHTeam team : this.p.getTeamManager().getTeams()) { - teamNames.add(team.getName()); - } - return getAutocompleteSuggestions(args[2], teamNames); - } - } - - else if(args.length >= 4) { // Autocompletion for team names – multiple words autocompletion - if(args[1].equalsIgnoreCase("join") || args[1].equalsIgnoreCase("remove")) { - ArrayList<String> teamNames = new ArrayList<String>(); - for(UHTeam team : this.p.getTeamManager().getTeams()) { - teamNames.add(team.getName()); - } - if(args[1].equalsIgnoreCase("join")) { // /uh team join <player> <?> - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 3), teamNames, args.length - 4); - } - else if(args[1].equalsIgnoreCase("remove")) { // /uh team remove <?> - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 2), teamNames, args.length - 3); - } - } - } - } - - /** Autocompletion for /uh spawns **/ - else if(args[0].equalsIgnoreCase("spawns")) { - // /uh spawns <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getSpawnsCommands()); - } - - if(args.length >= 3 && args[1].equalsIgnoreCase("generate")) { // /uh spawns generate <?> - - // Generation methods - /uh spawns generate <?> - if(args.length == 3) { - ArrayList<String> suggested = new ArrayList<String>(); - suggested.add("random"); - suggested.add("circular"); - suggested.add("grid"); - - return getAutocompleteSuggestions(args[2], suggested); - } - - // Worlds - /uh spawns generate - - - - - - <?> - else if(args.length == 9) { - ArrayList<String> suggested = new ArrayList<String>(); - for(World world : p.getServer().getWorlds()) { - suggested.add(world.getName()); - } - - return getAutocompleteSuggestions(args[8], suggested); - } - } - } - - /** Autocompletion for /uh tp **/ - else if(args[0].equalsIgnoreCase("tp")) { - // /uh tp <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getTPCommands()); - } - - // /uh tp spectators: no autocomplete needed (only pseudonyms). - - if(args[1].equalsIgnoreCase("team")) { - ArrayList<String> teamNames = new ArrayList<String>(); - for(UHTeam team : this.p.getTeamManager().getTeams()) { - teamNames.add(team.getName()); - } - - // /uh tp team <x> <y> <z> <?>: autocompletion for team names – multiple words autocompletion - if(args.length >= 6) { - List<String> suggestions = getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 5), teamNames, args.length - 6); - - if(suggestions.size() != 0) { - return suggestions; - } - } - - // /uh tp team <target> <?>: autocompletion for team names – multiple words autocompletion - if(args.length >= 4) { - try { - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, 3), teamNames, args.length - 4); - } catch(IllegalArgumentException ignored) { - // Temp workaround for an unknown bug. - } - } - } - } - - /** Autocompletion for /uh timers **/ - else if(args[0].equalsIgnoreCase("timers")) { - // /uh timers <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getTimersCommands()); - } - - int timerNameIndex = 0; - if(args.length >= 3) { // /uh timers <subcommand> <timer name ...> - if(args[1].equalsIgnoreCase("display") - || args[1].equalsIgnoreCase("hide") - || args[1].equalsIgnoreCase("start") - || args[1].equalsIgnoreCase("pause") - || args[1].equalsIgnoreCase("resume") - || args[1].equalsIgnoreCase("stop") - || args[1].equalsIgnoreCase("remove")) { - timerNameIndex = 2; - } - } - - if(args.length >= 4) { // /uh timers <subcommand> <duration> <timer name ...> - if(args[1].equalsIgnoreCase("set") || args[1].equalsIgnoreCase("add")) { - timerNameIndex = 3; - } - } - - if(timerNameIndex != 0) { - List<String> timersName = new ArrayList<String>(); - for(UHTimer timer : p.getTimerManager().getTimers()) { - timersName.add(timer.getName()); - } - - return getAutocompleteSuggestions(UHUtils.getStringFromCommandArguments(args, timerNameIndex), timersName, args.length - timerNameIndex - 1); - } - } - - /** Autocompletion for /uh spec **/ - else if(args[0].equalsIgnoreCase("spec")) { - - // /uh spec <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getSpecCommands()); - } - - if(args.length == 3) { - - if(args[1].equalsIgnoreCase("remove")) { // /uh spec remove <?>: autocompletion for spectators only (not all players) - ArrayList<String> spectatorsList = new ArrayList<String>(); - for(String spectator : p.getGameManager().getStartupSpectators()) { - spectatorsList.add(spectator); - } - return getAutocompleteSuggestions(args[2], spectatorsList); - } - - } - } - - /** Autocompletion for /uh start **/ - else if(args[0].equalsIgnoreCase("start")) { - ArrayList<String> commandSuggested = new ArrayList<String>(); - - if(args.length == 2) { // /uh start <?> - commandSuggested.add("slow"); - return getAutocompleteSuggestions(args[1], commandSuggested); - } - - else if(args.length == 3 && args[1].equalsIgnoreCase("slow")) { // /uh start slow <?> - commandSuggested.add("go"); - return getAutocompleteSuggestions(args[2], commandSuggested); - } - } - - /** Autocompletion for /uh tpback **/ - else if(args[0].equalsIgnoreCase("tpback")) { - if(args.length == 3) { // /uh tpback <player> <?=force> - ArrayList<String> tpBackSuggest = new ArrayList<String>(); - tpBackSuggest.add("force"); - return getAutocompleteSuggestions(args[2], tpBackSuggest); - } - } - - /** Autocompletion for /uh kill **/ - else if(args[0].equalsIgnoreCase("kill")) { - if(args.length == 2) { // /uh kill <?> - ArrayList<String> suggestions = new ArrayList<String>(); - for(OfflinePlayer player : p.getGameManager().getAlivePlayers()) { - suggestions.add(player.getName()); - } - return getAutocompleteSuggestions(args[1], suggestions); - } - } - - /** Autocompletion for /uh freeze **/ - else if(args[0].equalsIgnoreCase("freeze")) { - - // /uh freeze <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getFreezeCommands()); - } - - } - - /** Autocompletion for /uh border **/ - else if(args[0].equalsIgnoreCase("border")) { - - // /uh border <?> - if(args.length == 2) { - return getAutocompleteSuggestions(args[1], p.getCommandManager().getBorderCommands()); - } - - else if(args[1].equalsIgnoreCase("warning") && args.length == 3) { // /uh border warning <?=cancel> - ArrayList<String> commandSuggested = new ArrayList<String>(); - commandSuggested.add("cancel"); - return getAutocompleteSuggestions(args[2], commandSuggested); - } - - else if(args[1].equalsIgnoreCase("set") && args.length == 4) { // /uh border set <diameter> <?=force> - ArrayList<String> commandSuggested = new ArrayList<String>(); - commandSuggested.add("force"); - return getAutocompleteSuggestions(args[3], commandSuggested); - } - - } - - return null; - } - - - /** - * Returns a list of autocompletion suggestions based on what the user typed and on a list of - * available commands. - * - * @param typed What the user typed. This string needs to include <em>all</em> the words typed. - * @param suggestionsList The list of the suggestions. - * @param numberOfWordsToIgnore If non-zero, this number of words will be ignored at the beginning of the string. This is used to handle multiple-words autocompletion. - * - * @return The list of matching suggestions. - */ - private List<String> getAutocompleteSuggestions(String typed, List<String> suggestionsList, int numberOfWordsToIgnore) { - List<String> list = new ArrayList<String>(); - - // For each suggestion: - // - if there isn't any world to ignore, we just compare them; - // - else, we removes the correct number of words at the beginning of the string; - // then, if the raw suggestion matches the typed text, we adds to the suggestion list - // the filtered suggestion, because the Bukkit's autocompleter works on a “per-word” basis. - - for(String rawSuggestion : suggestionsList) { - String suggestion = ""; - - if(numberOfWordsToIgnore == 0) { - suggestion = rawSuggestion; - } - else { - // Not the primary use, but, hey! It works. - suggestion = UHUtils.getStringFromCommandArguments(rawSuggestion.split(" "), numberOfWordsToIgnore); - } - - if(rawSuggestion.toLowerCase().startsWith(typed.toLowerCase())) { - list.add(suggestion); - } - } - - Collections.sort(list, Collator.getInstance()); - - return list; - } - - /** - * Returns a list of autocompletion suggestions based on what the user typed and on a list of - * available commands. - * - * @param typed What the user typed. - * @param suggestionsList The list of the suggestions. - * - * @return The list of matching suggestions. - */ - private List<String> getAutocompleteSuggestions(String typed, List<String> suggestionsList) { - return getAutocompleteSuggestions(typed, suggestionsList, 0); - } - -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/BorderManager.java b/src/main/java/me/azenet/UHPlugin/borders/BorderManager.java deleted file mode 100644 index b0e52de..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/BorderManager.java +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.borders; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.exceptions.CannotGenerateWallsException; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.task.BorderWarningTask; -import me.azenet.UHPlugin.timers.UHTimer; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.HashSet; - - -public class BorderManager { - - private UHPlugin p = null; - private I18n i = null; - - private Integer currentBorderDiameter = null; - - private Integer warningSize = 0; - private BukkitRunnable warningTask = null; - - private Boolean warningFinalTimeEnabled = false; - private String warningTimerName = null; - private CommandSender warningSender = null; - - private MapShape mapShape = null; - - - public BorderManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - - this.warningTimerName = i.t("borders.warning.nameTimer"); - - this.currentBorderDiameter = p.getConfig().getInt("map.size"); - this.mapShape = MapShape.fromString(p.getConfig().getString("map.shape")); - - if(mapShape == null) { - p.getLogger().warning("Invalid shape '" + p.getConfig().getString("map.shape") + "'; using 'squared' instead."); - mapShape = MapShape.SQUARED; - } - } - - /** - * Sets the shape of the map. Updates the WorldBorder too. - * - * @param shape The shape. - */ - public void setMapShape(MapShape shape) { - this.mapShape = shape; - - p.getWorldBorderIntegration().setupBorders(); // Updates the WB border if needed - } - - /** - * Returns the current shape of the map. - * - * @return The shape. - */ - public MapShape getMapShape() { - return mapShape; - } - - /** - * Checks if a given location is inside the border with the given diameter. - * The check is performed for a circular or squared border, following the configuration. - * - * @param location - * @param diameter - * @return - */ - public boolean isInsideBorder(Location location, double diameter) { - if(!location.getWorld().getEnvironment().equals(Environment.NORMAL)) { // The nether/end are not limited. - return true; - } - - return mapShape.getShape().isInsideBorder(location, diameter, location.getWorld().getSpawnLocation()); - } - - /** - * Checks if a given location is inside the border with the current diameter. - * The check is performed for a circular or squared border, following the configuration. - * - * @param location - * @return - */ - public boolean isInsideBorder(Location location) { - return this.isInsideBorder(location, getCurrentBorderDiameter()); - } - - /** - * Returns the distance from the location to the border, if the location is outside this border. - * If it is inside, or in another world, returns 0. - * - * @param location - * @param diameter - * @return - */ - public double getDistanceToBorder(Location location, double diameter) { - return mapShape.getShape().getDistanceToBorder(location, diameter, location.getWorld().getSpawnLocation()); - } - - - /** - * Returns a list of the players outside a border with the given diameter. - * The check is performed for a circular or squared border, following the configuration. - * - * @param diameter - * @return - */ - public HashSet<Player> getPlayersOutside(int diameter) { - HashSet<Player> playersOutside = new HashSet<Player>(); - - for(final Player player : p.getGameManager().getOnlineAlivePlayers()) { - if(!isInsideBorder(player.getLocation(), diameter)) { - playersOutside.add(player); - } - } - - return playersOutside; - } - - /** - * Returns the diameter used to check if the players are inside the wall. - * - * If the wall is circular, the diameter used to check must be bigger to avoid false positives - * if a player is in an angle of the circular wall. - * - * “+3” ? Experimental. - * - * @return - */ - public int getCheckDiameter() { - if(getMapShape() == MapShape.CIRCULAR) { - return getCurrentBorderDiameter() + 3; - } - else { - return getCurrentBorderDiameter(); - } - } - - /** - * Returns the size of the future border, used in the warning messages sent to the - * players out of this future border. - * - * @return - */ - public int getWarningSize() { - return this.warningSize; - } - - /** - * Returns true if there is currently a warning with a time left displayed. - * - * @return - */ - public boolean getWarningFinalTimeEnabled() { - return this.warningFinalTimeEnabled; - } - - /** - * Returns the sender of the last warning configured. - * - * @return - */ - public CommandSender getWarningSender() { - return this.warningSender; - } - - /** - * Sets the size of the future border, used in the warning messages sent to the - * players out of this future border. - * - * This also starts the display of the warning messages, every 90 seconds by default - * (configurable, see config.yml, map.border.warningInterval). - * - * If timeLeft is not null, the time available for the players to go inside the future - * border is displayed in the warning message. - * - * @param diameter - * @param timeLeft The time available for the players to go inside the future border (minutes). - */ - public void setWarningSize(int diameter, int timeLeft, CommandSender sender) { - cancelWarning(); - - this.warningSize = diameter; - - if(timeLeft != 0) { - UHTimer timer = new UHTimer(this.warningTimerName); - timer.setDuration(timeLeft * 60); - - p.getTimerManager().registerTimer(timer); - - timer.start(); - } - - if(sender != null) { - this.warningSender = sender; - } - - warningTask = new BorderWarningTask(p); - warningTask.runTaskTimer(p, 20L, 20L * p.getConfig().getInt("map.border.warningInterval", 90)); - } - - /** - * Sets the size of the future border, used in the warning messages sent to the - * players out of this future border. - * - * This also starts the display of the warning messages, every 90 seconds by default - * (configurable, see config.yml, map.border.warningInterval). - * - * @param diameter - */ - public void setWarningSize(int diameter) { - setWarningSize(diameter, 0, null); - } - - /** - * Returns the UHTimer object representing the countdown before the next border reduction. - * <p> - * Returns null if there isn't any countdown running currently. - * - * @return The timer. - */ - public UHTimer getWarningTimer() { - return p.getTimerManager().getTimer(this.warningTimerName); - } - - /** - * Stops the display of the warning messages. - */ - public void cancelWarning() { - if(warningTask != null) { - try { - warningTask.cancel(); - } catch(IllegalStateException e) { - - } - } - - UHTimer timer = getWarningTimer(); - if(timer != null) { - timer.stop(); - p.getTimerManager().unregisterTimer(timer); - } - } - - /** - * Returns the current border diameter. - * - * @return - */ - public int getCurrentBorderDiameter() { - return this.currentBorderDiameter; - } - - /** - * Changes the current border diameter. - * This also reconfigures WorldBorder (if present). - * - * If WorldBorder is installed, all players out of this new border will be teleported inside the new one. - * Else, nothing will happens. - * - * @param diameter - */ - public void setCurrentBorderDiameter(int diameter) { - cancelWarning(); - this.currentBorderDiameter = diameter; - - p.getWorldBorderIntegration().setupBorders(); // Updates the WB border if needed - } - - - /** - * Sends a list of the players outside the given border to the specified sender. - * - * @param to The player/console to send the check. - * @param diameter The diameter of the border to be checked. - */ - public void sendCheckMessage(CommandSender to, int diameter) { - HashSet<Player> playersOutside = getPlayersOutside(diameter); - - if(playersOutside.size() == 0) { - to.sendMessage(i.t("borders.check.allPlayersInside")); - } - else { - to.sendMessage(i.t("borders.check.countPlayersOutside", String.valueOf(playersOutside.size()))); - for(Player player : getPlayersOutside(diameter)) { - double distance = getDistanceToBorder(player.getLocation(), diameter); - if(distance > 150) { - to.sendMessage(i.t("borders.check.itemPlayerFar", player.getName())); - } - else if(distance > 25) { - to.sendMessage(i.t("borders.check.itemPlayerClose", player.getName())); - } - else { - to.sendMessage(i.t("borders.check.itemPlayerVeryClose", player.getName())); - } - } - } - } - - /** - * - * @param world The world were the walls will be built in. - * @throws CannotGenerateWallsException - */ - public void generateWalls(World world) throws CannotGenerateWallsException { - Integer wallHeight = p.getConfig().getInt("map.wall.height"); - - Material wallBlockAir = Material.matchMaterial(p.getConfig().getString("map.wall.block.replaceAir")); - Material wallBlockSolid = Material.matchMaterial(p.getConfig().getString("map.wall.block.replaceSolid")); - - if(wallBlockAir == null || !wallBlockAir.isSolid() || wallBlockSolid == null || !wallBlockSolid.isSolid()) { - throw new CannotGenerateWallsException("Cannot generate the walls: invalid blocks set in the config"); - } - - mapShape.getWallGeneratorInstance(p, wallBlockAir, wallBlockSolid).build(world, getCurrentBorderDiameter(), wallHeight); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/MapShape.java b/src/main/java/me/azenet/UHPlugin/borders/MapShape.java deleted file mode 100644 index f9d62b6..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/MapShape.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.generators.CircularWallGenerator; -import me.azenet.UHPlugin.borders.generators.SquaredWallGenerator; -import me.azenet.UHPlugin.borders.generators.WallGenerator; -import me.azenet.UHPlugin.borders.shapes.CircularMapShape; -import me.azenet.UHPlugin.borders.shapes.MapShapeDescriptor; -import me.azenet.UHPlugin.borders.shapes.SquaredMapShape; -import org.bukkit.Material; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; - - -public enum MapShape { - - CIRCULAR(new CircularMapShape(), CircularWallGenerator.class), - SQUARED(new SquaredMapShape(), SquaredWallGenerator.class); - - - private MapShapeDescriptor shape; - private Class<? extends WallGenerator> generatorClass; - - /** - * @param generator The wall generator class associated with this shape. - */ - private MapShape(MapShapeDescriptor shape, Class<? extends WallGenerator> generator) { - this.shape = shape; - this.generatorClass = generator; - } - - /** - * Returns a new instance of the wall generator for this shape. - * - * @return The instance. - */ - public WallGenerator getWallGeneratorInstance(UHPlugin p, Material wallBlockAir, Material wallBlockSolid) { - - try { - Constructor constructor = generatorClass.getConstructor(UHPlugin.class, Material.class, Material.class); - return (WallGenerator) constructor.newInstance(p, wallBlockAir, wallBlockSolid); - - } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) { - p.getLogger().log(Level.SEVERE, "Cannot instantiate the walls generator: invalid class."); - e.printStackTrace(); - return null; - } - } - - /** - * Returns the shape descriptor. - * - * @return The shape. - */ - public MapShapeDescriptor getShape() { - return shape; - } - - /** - * Returns a shape based on his name. - * - * <p>Not case sensitive.</p> - * - * @param name The name. - * @return The MapShape, or {@code null} if not found. - */ - public static MapShape fromString(String name) { - try { - return MapShape.valueOf(name.trim().toUpperCase()); - } catch(IllegalArgumentException e) { - return null; - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/exceptions/CannotGenerateWallsException.java b/src/main/java/me/azenet/UHPlugin/borders/exceptions/CannotGenerateWallsException.java deleted file mode 100644 index 6cbb566..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/exceptions/CannotGenerateWallsException.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.exceptions; - -public class CannotGenerateWallsException extends Exception { - - public CannotGenerateWallsException(String message) { - super(message); - } - -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/exceptions/UnknownWallGenerator.java b/src/main/java/me/azenet/UHPlugin/borders/exceptions/UnknownWallGenerator.java deleted file mode 100644 index de98d1a..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/exceptions/UnknownWallGenerator.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.exceptions; - -public class UnknownWallGenerator extends Exception { - - public UnknownWallGenerator(String message) { - super(message); - } - -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/generators/CircularWallGenerator.java b/src/main/java/me/azenet/UHPlugin/borders/generators/CircularWallGenerator.java deleted file mode 100644 index 66e2d7d..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/generators/CircularWallGenerator.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.generators; - -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; - - -public class CircularWallGenerator extends WallGenerator { - - public CircularWallGenerator(UHPlugin p, Material wallBlockAir, Material wallBlockSolid) { - super(p, wallBlockAir, wallBlockSolid); - } - - /** - * Builds a wall in the world. - * - * @param world The world the wall will be built in. - * @param diameter The diameter of the wall. - * @param wallHeight The height of the wall. - */ - @Override - public void build(World world, int diameter, int wallHeight) { - // Only one quarter of the circle is explicitly set, the other parts are generated - // following the first quarter. - // The quarter chosen to be explicitly generated if the one on the South-East, - // starting at x = xSpawn+radius ; z = zSpawn and ending at x = xSpawn ; z = zSpawn+radius. - - // In each step we gets the three blocks susceptible to be the next block and we calculates the - // distance from the center to these blocks. - // The good block if the one with the closest distance to the radius. - - Integer radius = (int) Math.floor(diameter/2); - - Integer xSpawn = world.getSpawnLocation().getBlockX(); - Integer ySpawn = world.getSpawnLocation().getBlockY(); - Integer zSpawn = world.getSpawnLocation().getBlockZ(); - - // First block. - Block currentBlock = world.getBlockAt((int) (xSpawn + radius), ySpawn, zSpawn); - - Block candidate1; - Block candidate2; - Block candidate3; - - // Infinite loop broken when the generation is done. - while(true) { - - // 1) the current point, the symmetries and the opposite point are built. - this.buildWallPoint(world, currentBlock.getX(), currentBlock.getZ(), wallHeight, diameter); - - - // 2) the two candidates are found, except if the build is finished. - if(currentBlock.getX() == xSpawn) { - // END - break; - } - - candidate1 = world.getBlockAt(currentBlock.getX() - 1, ySpawn, currentBlock.getZ()); - candidate2 = world.getBlockAt(currentBlock.getX() - 1, ySpawn, currentBlock.getZ() + 1); - candidate3 = world.getBlockAt(currentBlock.getX(), ySpawn, currentBlock.getZ() + 1); - - - // 3) The good block is selected - Double distanceCandidate1ToRef = Math.abs((candidate1.getLocation().distance(world.getSpawnLocation()) - radius)); - Double distanceCandidate2ToRef = Math.abs((candidate2.getLocation().distance(world.getSpawnLocation()) - radius)); - Double distanceCandidate3ToRef = Math.abs((candidate3.getLocation().distance(world.getSpawnLocation()) - radius)); - - if(distanceCandidate1ToRef < distanceCandidate2ToRef && distanceCandidate1ToRef < distanceCandidate3ToRef) { // The first is better - currentBlock = candidate1; - } - else if(distanceCandidate2ToRef < distanceCandidate1ToRef && distanceCandidate2ToRef < distanceCandidate3ToRef) { // The second is better - currentBlock = candidate2; - } - else { - currentBlock = candidate3; - } - } - } - - - /** - * Builds 4 "towers" of the wall, from y=0 to y=wallHeight, at the given coordinates, and - * the symmetric points. - * - * @param world - * @param x - * @param z - * @param wallHeight - * @param diameter - */ - private void buildWallPoint(World world, int x, int z, int wallHeight, int diameter) { - - WallPosition positionOriginal; - WallPosition positionSymmetricX; - WallPosition positionSymmetricZ; - WallPosition positionOpposite; - - Integer xSpawn = world.getSpawnLocation().getBlockX(); - Integer zSpawn = world.getSpawnLocation().getBlockZ(); - - // We generates first the bedrock at y=0 - world.getBlockAt(x, 0, z).setType(Material.BEDROCK); - world.getBlockAt(x - 2*(x - xSpawn), 0, z).setType(Material.BEDROCK); - world.getBlockAt(x, 0, z + 2*(zSpawn - z)).setType(Material.BEDROCK); - world.getBlockAt(x - 2*(x - xSpawn), 0, z + 2*(zSpawn - z)).setType(Material.BEDROCK); - - - // Following the way the wall is generated, the position of the original - // "tower" can only be « SOUTH » or « EAST ». - if(z > Math.floor(diameter/2)) { - positionOriginal = WallPosition.SOUTH; - positionSymmetricX = WallPosition.SOUTH; - positionSymmetricZ = WallPosition.NORTH; - positionOpposite = WallPosition.NORTH; - } - else { - positionOriginal = WallPosition.EAST; - positionSymmetricX = WallPosition.WEST; - positionSymmetricZ = WallPosition.EAST; - positionOpposite = WallPosition.WEST; - } - - // The 4 towers are built. - for(int y = 1; y <= wallHeight; y++) { - setBlock(world.getBlockAt(x, y, z ), positionOriginal); - setBlock(world.getBlockAt(x - 2*(x - xSpawn), y, z ), positionSymmetricX); - setBlock(world.getBlockAt(x, y, z + 2*(zSpawn - z)), positionSymmetricZ); - setBlock(world.getBlockAt(x - 2*(x - xSpawn), y, z + 2*(zSpawn - z)), positionOpposite); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/generators/SquaredWallGenerator.java b/src/main/java/me/azenet/UHPlugin/borders/generators/SquaredWallGenerator.java deleted file mode 100644 index af376ac..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/generators/SquaredWallGenerator.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.generators; - -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; - - -public class SquaredWallGenerator extends WallGenerator { - - public SquaredWallGenerator(UHPlugin p, Material wallBlockAir, Material wallBlockSolid) { - super(p, wallBlockAir, wallBlockSolid); - } - - /** - * Builds a wall in the world. - * - * @param world The world the wall will be built in. - * @param diameter The diameter of the wall. - * @param wallHeight The height of the wall. - */ - @Override - public void build(World world, int diameter, int wallHeight) { - Integer halfDiameter = (int) Math.floor(diameter/2); - - Location spawn = world.getSpawnLocation(); - Integer limitXInf = spawn.add(-halfDiameter, 0, 0).getBlockX(); - - spawn = world.getSpawnLocation(); - Integer limitXSup = spawn.add(halfDiameter, 0, 0).getBlockX(); - - spawn = world.getSpawnLocation(); - Integer limitZInf = spawn.add(0, 0, -halfDiameter).getBlockZ(); - - spawn = world.getSpawnLocation(); - Integer limitZSup = spawn.add(0, 0, halfDiameter).getBlockZ(); - - for (Integer x = limitXInf; x <= limitXSup; x++) { - world.getBlockAt(x, 1, limitZInf).setType(Material.BEDROCK); - world.getBlockAt(x, 1, limitZSup).setType(Material.BEDROCK); - - for (Integer y = 2; y <= wallHeight; y++) { - setBlock(world.getBlockAt(x, y, limitZInf), WallPosition.NORTH); - setBlock(world.getBlockAt(x, y, limitZSup), WallPosition.SOUTH); - } - } - - for (Integer z = limitZInf + 1; z <= limitZSup - 1; z++) { - world.getBlockAt(limitXInf, 1, z).setType(Material.BEDROCK); - world.getBlockAt(limitXSup, 1, z).setType(Material.BEDROCK); - - for (Integer y = 2; y <= wallHeight; y++) { - setBlock(world.getBlockAt(limitXInf, y, z), WallPosition.WEST); - setBlock(world.getBlockAt(limitXSup, y, z), WallPosition.EAST); - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/generators/WallGenerator.java b/src/main/java/me/azenet/UHPlugin/borders/generators/WallGenerator.java deleted file mode 100644 index a9e45d3..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/generators/WallGenerator.java +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.borders.generators; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; - - -public abstract class WallGenerator { - - private UHPlugin p; - private I18n i; - - private Material wallBlockAir = null; - private Material wallBlockSolid = null; - - private int blocksSet = 0; - - public WallGenerator(UHPlugin p, Material wallBlockAir, Material wallBlockSolid) { - this.p = p; - this.i = p.getI18n(); - - this.wallBlockAir = wallBlockAir; - this.wallBlockSolid = wallBlockSolid; - } - - - /** - * Builds a wall in the world. - * - * @param world The world the wall will be built in. - * @param diameter The diameter of the wall. - * @param wallHeight The height of the wall. - */ - public abstract void build(World world, int diameter, int wallHeight); - - - /** - * Sets a block according to his environment. - * If the block replaces a "air/tree" block, or if it is next to a transparent block, it needs to be a - * "wall.block.replaceAir" block. - * In all other cases, it needs to be a "wall.block.replaceSolid" one. - * - * @param block The block to set. - * @param position The position of the current wall in the world - */ - protected void setBlock(Block block, WallPosition position) { - // The block is a transparent block or a tree - if(isBlockTransparentOrNatural(block.getType())) { - block.setType(wallBlockAir); - } - // We set the block according to the block near it inside the border. - else { - Material innerMaterial = getInnerBlock(block, position).getType(); - if(isBlockTransparentOrNatural(innerMaterial)) { - block.setType(wallBlockAir); - } - else { - block.setType(wallBlockSolid); - } - } - - this.blocksSet++; - } - - /** - * Checks if a block is transparent or is part of a tree. - * Used to generate the wall. - * - * @return boolean True if the block is transparent, or part of a tree/a giant mushroom/a - * generated structure/etc. - */ - protected Boolean isBlockTransparentOrNatural(Material blockType) { - if(blockType.isTransparent()) { - return true; - } - - switch(blockType) { - case GLASS: // The glass isn't a transparent block for the `isTransparent` method. - case STAINED_GLASS: - case THIN_GLASS: - case STAINED_GLASS_PANE: - case LEAVES: - case LEAVES_2: - case LOG: - case LOG_2: - case CHEST: // Avoid a cube of the solid block where there where a chest. - case TRAPPED_CHEST: - case ENDER_CHEST: - case WATER: - case STATIONARY_WATER: - case BED_BLOCK: - case PISTON_STICKY_BASE: // Same idea (in jungle temples). - case PISTON_BASE: - case BOOKSHELF: // Same idea (in villages & fortresses). - case MOB_SPAWNER: // Same idea (in dungeons). - case SIGN_POST: - case WALL_SIGN: - case ICE: // Same idea (in cold biomes). - case PACKED_ICE: - case CACTUS: // Same idea (in deserts) - case FENCE: - case FENCE_GATE: - case IRON_FENCE: - case NETHER_FENCE: - case PUMPKIN: - case MELON_BLOCK: // Same idea (in jungles) - case GLOWSTONE: // Same idea (in the Nether - why not?) - case JACK_O_LANTERN: - case HUGE_MUSHROOM_1: // Same idea (in dark forests). - case HUGE_MUSHROOM_2: - case CAKE_BLOCK: // It may be a lie, but hey, why not. - case BEACON: - case COBBLE_WALL: - case ANVIL: - return true; - default: - return false; - } - } - - /** - * Gets the block left to the given block inside the border. - * - * @param block The reference block. - * @param position The position of the wall currently build. - */ - protected Block getInnerBlock(Block block, WallPosition position) { - // Just for readability. - World world = block.getWorld(); - Integer x = block.getX(); - Integer y = block.getY(); - Integer z = block.getZ(); - - switch(position) { - case EAST: - return world.getBlockAt(x - 1, y, z); - case NORTH: - return world.getBlockAt(x, y, z + 1); - case SOUTH: - return world.getBlockAt(x, y, z - 1); - case WEST: - return world.getBlockAt(x + 1, y, z); - default: // wait what? - return null; - } - } - - public int getBlocksSet() { - return blocksSet; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/generators/WallPosition.java b/src/main/java/me/azenet/UHPlugin/borders/generators/WallPosition.java deleted file mode 100644 index d11cc18..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/generators/WallPosition.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.borders.generators; - -/** - * Used to determine in witch wall we are, to get the "inner" block. - * - * North: small Z - * South: big Z - * East: big X - * West: small X - */ -public enum WallPosition { - NORTH, - SOUTH, - EAST, - WEST -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/shapes/CircularMapShape.java b/src/main/java/me/azenet/UHPlugin/borders/shapes/CircularMapShape.java deleted file mode 100644 index 6e70bee..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/shapes/CircularMapShape.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.shapes; - -import org.bukkit.Location; -import org.bukkit.World; - - -public class CircularMapShape implements MapShapeDescriptor { - - /** - * Returns true if the given location is inside the map. - * - * @param location The location to check. - * @param diameter The diameter of the map. - * @param center The center of the map. - * - * @return {@code true} if the given location is inside the map. - */ - @Override - public boolean isInsideBorder(final Location location, final Double diameter, final Location center) { - Location centerRef = center.clone(); - centerRef.setY(location.getY()); - - return (location.distance(centerRef) <= Math.floor(diameter / 2)); - } - - /** - * Returns the distance between the given location and the border with this diameter. - * - * @param location The distance will be calculated between this location and the closest point of the border. - * @param diameter The diameter of the border. - * @param center The center of the border. - * - * @return The distance between the given {@code location} and the closest point of the border.<br /> - * {@code -1} if the location is inside the border. - */ - @Override - public double getDistanceToBorder(final Location location, final Double diameter, final Location center) { - if(!location.getWorld().getEnvironment().equals(World.Environment.NORMAL)) { // The nether/end are not limited. - return -1; - } - - if(isInsideBorder(location, diameter, center)) { - return -1; - } - - Location centerRef = center.clone(); - centerRef.setY(location.getY()); - - return (location.distance(centerRef) - Math.floor(diameter/2)); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/shapes/MapShapeDescriptor.java b/src/main/java/me/azenet/UHPlugin/borders/shapes/MapShapeDescriptor.java deleted file mode 100644 index 4f989bf..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/shapes/MapShapeDescriptor.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.shapes; - -import org.bukkit.Location; - - -/** - * Represents a shape of the map. - */ -public interface MapShapeDescriptor { - - /** - * Returns true if the given location is inside the map. - * - * @param location The location to check. - * @param diameter The diameter of the map. - * @param center The center of the map. - * - * @return {@code true} if the given location is inside the map. - */ - public boolean isInsideBorder(final Location location, final Double diameter, final Location center); - - /** - * Returns the distance between the given location and the border with this diameter. - * - * @param location The distance will be calculated between this location and the closest point of the border. - * @param diameter The diameter of the border. - * @param center The center of the border. - * - * @return The distance between the given {@code location} and the closest point of the border.<br /> - * {@code -1} if the location is inside the border. - */ - public double getDistanceToBorder(final Location location, final Double diameter, final Location center); - -} diff --git a/src/main/java/me/azenet/UHPlugin/borders/shapes/SquaredMapShape.java b/src/main/java/me/azenet/UHPlugin/borders/shapes/SquaredMapShape.java deleted file mode 100644 index a13c144..0000000 --- a/src/main/java/me/azenet/UHPlugin/borders/shapes/SquaredMapShape.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.borders.shapes; - -import org.bukkit.Location; -import org.bukkit.World; - - -public class SquaredMapShape implements MapShapeDescriptor { - - /** - * Returns true if the given location is inside the map. - * - * @param location The location to check. - * @param diameter The diameter of the map. - * @param center The center of the map. - * - * @return {@code true} if the given location is inside the map. - */ - @Override - public boolean isInsideBorder(final Location location, final Double diameter, final Location center) { - Integer halfMapSize = (int) Math.floor(diameter/2); - Integer x = location.getBlockX(); - Integer z = location.getBlockZ(); - - Integer limitXInf = center.clone().add(-halfMapSize, 0, 0).getBlockX(); - Integer limitXSup = center.clone().add(halfMapSize, 0, 0) .getBlockX(); - Integer limitZInf = center.clone().add(0, 0, -halfMapSize).getBlockZ(); - Integer limitZSup = center.clone().add(0, 0, halfMapSize) .getBlockZ(); - - return !(x < limitXInf || x > limitXSup || z < limitZInf || z > limitZSup); - } - - /** - * Returns the distance between the given location and the border with this diameter. - * - * @param location The distance will be calculated between this location and the closest point of the border. - * @param diameter The diameter of the border. - * @param center The center of the border. - * - * @return The distance between the given {@code location} and the closest point of the border.<br /> - * {@code -1} if the location is inside the border. - */ - @Override - public double getDistanceToBorder(final Location location, final Double diameter, final Location center) { - if(!location.getWorld().getEnvironment().equals(World.Environment.NORMAL)) { // The nether/end are not limited. - return -1; - } - - if(isInsideBorder(location, diameter, center)) { - return -1; - } - - Integer halfMapSize = (int) Math.floor(diameter/2); - Integer x = location.getBlockX(); - Integer z = location.getBlockZ(); - - Integer limitXInf = center.clone().add(-halfMapSize, 0, 0).getBlockX(); - Integer limitXSup = center.clone().add(halfMapSize, 0, 0) .getBlockX(); - Integer limitZInf = center.clone().add(0, 0, -halfMapSize).getBlockZ(); - Integer limitZSup = center.clone().add(0, 0, halfMapSize) .getBlockZ(); - - if(x > limitXSup && z < limitZSup && z > limitZInf) { // East of the border - return Math.abs(x - limitXSup); - } - else if(x < limitXInf && z < limitZSup && z > limitZInf) { // West of the border - return Math.abs(x - limitXInf); - } - else if(z > limitZSup && x < limitXSup && x > limitXInf) { // South of the border - return Math.abs(z - limitZSup); - } - else if(z < limitZInf && x < limitXSup && x > limitXInf) { // North of the border - return Math.abs(z - limitZInf); - } - else if(x > limitXSup && z < limitZInf) { // North-East - return (int) location.distance(new Location(location.getWorld(), limitXSup, location.getBlockY(), limitZInf)); - } - else if(x > limitXSup && z > limitZSup) { // South-East - return (int) location.distance(new Location(location.getWorld(), limitXSup, location.getBlockY(), limitZSup)); - } - else if(x < limitXInf && z > limitZSup) { // South-West - return (int) location.distance(new Location(location.getWorld(), limitXInf, location.getBlockY(), limitZSup)); - } - else if(x < limitXInf && z < limitZInf) { // North-West - return (int) location.distance(new Location(location.getWorld(), limitXInf, location.getBlockY(), limitZInf)); - } - else { - return -1; // Should never happen. - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/AbstractCommandExecutor.java b/src/main/java/me/azenet/UHPlugin/commands/AbstractCommandExecutor.java deleted file mode 100644 index 55e0f52..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/AbstractCommandExecutor.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.commands; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.utils.CommandUtils; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -public abstract class AbstractCommandExecutor implements TabExecutor { - - private UHPlugin p; - private I18n i; - - /** - * Stores the main commands, i.e. the commands registered in the {@code plugin.yml} file. - */ - private Map<String, UHCommand> mainCommands = new HashMap<>(); - - /** - * Stores the base permissions of these commands. - */ - private Map<String, String> mainCommandsPermissions = new HashMap<>(); - - public AbstractCommandExecutor(UHPlugin plugin) { - p = plugin; - i = p.getI18n(); - } - - /** - * Registers a main, root command. This command must be in the {@code plugin.yml}, or - * it will never be called. - * - * @param command The command. - * - * @throws IllegalArgumentException If the command class doesn't have the @Command - * annotation. - */ - public void registerCommand(UHCommand command) { - me.azenet.UHPlugin.commands.Command commandAnnotation = command.getClass().getAnnotation(me.azenet.UHPlugin.commands.Command.class); - if(commandAnnotation == null) { - throw new IllegalArgumentException("Cannot register a command without @Command annotation."); - } - - mainCommands.put(commandAnnotation.name(), command); - mainCommandsPermissions.put(commandAnnotation.name(), commandAnnotation.permission()); - } - - @Override - public boolean onCommand(CommandSender sender, org.bukkit.command.Command command, String alias, String[] args) { - UHCommand uhCommand = mainCommands.get(command.getName()); - if(uhCommand == null) { - return false; - } - try { - if(!sender.hasPermission(mainCommandsPermissions.get(command.getName()))) { - throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED); - } - - uhCommand.run(sender, CommandUtils.getSubcommandArguments(args)); - - } catch(CannotExecuteCommandException e) { - switch(e.getReason()) { - case NOT_ALLOWED: - sender.sendMessage(i.t("cmd.errorUnauthorized")); - break; - - case ONLY_AS_A_PLAYER: - break; - - case BAD_USE: - for(String line : uhCommand.help(sender)) { - sender.sendMessage(line); - } - break; - - case UNKNOWN: - break; - } - } - - return true; - } - - @Override - public List<String> onTabComplete(CommandSender sender, org.bukkit.command.Command command, String alias, String[] args) { - return null; - } - -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/CannotExecuteCommandException.java b/src/main/java/me/azenet/UHPlugin/commands/CannotExecuteCommandException.java deleted file mode 100644 index d151e96..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/CannotExecuteCommandException.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.commands; - -public class CannotExecuteCommandException extends Exception { - - public enum Reason { - NOT_ALLOWED, - ONLY_AS_A_PLAYER, - BAD_USE, - UNKNOWN - } - - private Reason reason; - - public CannotExecuteCommandException(Reason reason) { - this.reason = reason; - } - - public Reason getReason() { - return reason; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/Command.java b/src/main/java/me/azenet/UHPlugin/commands/Command.java deleted file mode 100644 index f4cbce4..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/Command.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.commands; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface Command { - /** - * The name of the command, needed to type in the console/chat to execute - * the (sub-)command. - */ - public String name(); - - /** - * The permission needed to execute this command. - * - * <p> - * If the {@code inheritPermission} option is unset or set to <code>false</code>, - * this permission is <strong>concatened to the parent permissions</strong>.<br /> - * As example, if the permission is set to {@code sb}, and if the parent command - * have the permission {@code cmd.norris}, the real permission of the command will - * be {@code cmd.norris.sb}. - * </p> - * <p> - * If this is left empty, or not set, the permission of the parent command will be used.<br /> - * If the parent command is {@code null} (i.e. this command is a root one), the command will be - * accessible to everyone. - * </p> - */ - public String permission() default ""; - - /** - * If this is set to {@code false}, the permission will be interpreted <em>as-is</em>, - * without concatenation with the permissions of the parent commands. - * - * <p> - * You should not set this to {@code false} if the command have sub-commands with this - * set to {@code true}, or weired behavior may happens. - * </p> - */ - public boolean inheritPermission() default true; -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/UHCommand.java b/src/main/java/me/azenet/UHPlugin/commands/UHCommand.java deleted file mode 100644 index c793bc3..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/UHCommand.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.commands; - - -import org.bukkit.command.CommandSender; - -import java.util.List; - - -public abstract class UHCommand { - - /** - * The parent command. - * - * <p> - * Example, for <code>/cmd foo bar</code>, the parent command of <code>bar</code> - * is the command <code>foo</code>. - * </p> - * <p> - * Without parent, <code>null</code>. - * </p> - */ - private UHCommand parent = null; - - /** - * Runs the command. - * - * @param sender The sender of the command. - * @param args The arguments passed to the command. - * - * @throws CannotExecuteCommandException If the command cannot be executed. - */ - public abstract void run(CommandSender sender, String[] args) throws CannotExecuteCommandException; - - /** - * Auto-completes ths command. - * - * @param sender The sender. - * @param args The arguments passed to the command. - * - * @return A list of suggestions. - */ - public abstract List<String> autocomplete(CommandSender sender, String[] args); - - /** - * Returns the help of this command. - * - * @param sender The sender. - * - * @return The help. One line per entry in the list. - */ - public abstract List<String> help(CommandSender sender); - - /** - * Sets the parent command of this command. Can be set only one time. - * - * @param parent The parent. - * @throws IllegalArgumentException If the parent command is already set. - */ - public void setParent(UHCommand parent) { - if(this.parent != null) { - throw new IllegalArgumentException("The parent command is already set!"); - } - - this.parent = parent; - } - - /** - * Returns the parent command. - * - * @return The parent; {@code null} if this command is a root one. - */ - public UHCommand getParent() { - return parent; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/UHCommandExecutor.java b/src/main/java/me/azenet/UHPlugin/commands/UHCommandExecutor.java deleted file mode 100644 index 71f68f1..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/UHCommandExecutor.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.commands; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.commands.commands.UH; -import me.azenet.UHPlugin.i18n.I18n; - - -public class UHCommandExecutor extends AbstractCommandExecutor { - - private UHPlugin p; - private I18n i; - - public UHCommandExecutor(UHPlugin plugin) { - super(plugin); - - p = plugin; - i = p.getI18n(); - - registerCommand(new UH(p)); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/UHComplexCommand.java b/src/main/java/me/azenet/UHPlugin/commands/UHComplexCommand.java deleted file mode 100644 index 2dd5cbb..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/UHComplexCommand.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.commands; - -import me.azenet.UHPlugin.utils.CommandUtils; -import org.bukkit.command.CommandSender; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - - -/** - * Represents a command with subcommands. - */ -public abstract class UHComplexCommand extends UHCommand { - - /** - * Stores the sub-commands of this complex command. - */ - private Map<String, UHCommand> subcommands = new HashMap<>(); - - /** - * Stores the permissions of the sub-commands. - */ - private Map<String, String> permissions = new HashMap<>(); - - /** - * This will be executed if this command is called without argument, - * or if there isn't any sub-command executor registered. - * - * @param sender The sender. - * @param args The arguments passed to the command. - */ - public abstract void runRoot(CommandSender sender, String[] args); - - /** - * Returns the general help for this command. - * - * <p> - * This help should be a one-line help, as it's displayed as the help - * for the parent commands. - * </p> - * - * @param sender The sender. - * - * @return The help, one line per entry in the list. - */ - public abstract List<String> helpRoot(CommandSender sender); - - /** - * Registers a subcommand of this command. - * A subcommand can be a complex command. - * - * @param command The command to register. - * - * @throws IllegalArgumentException If the command object don't have - * the {@code @}{@link Command} annotation. - */ - public void registerSubCommand(UHCommand command) { - Command commandAnnotation = command.getClass().getAnnotation(Command.class); - - if(commandAnnotation == null) { - throw new IllegalArgumentException("Cannot register a command without the @Command annotation."); - } - - command.setParent(this); - - String name = commandAnnotation.name(); - String permission = commandAnnotation.permission(); - - if(commandAnnotation.inheritPermission()) { - UHCommand parent = this; - while(parent != null) { - // The parent will always have the @Command annotation, because it is always - // added in this method and the presence of the annotation is checked. - Command parentAnnotation = parent.getClass().getAnnotation(Command.class); - if(!parentAnnotation.permission().isEmpty()) { - permission = parentAnnotation.permission() + "." + permission; - } - parent = parent.getParent(); - } - } - - // Let's save these permissions and executors. - subcommands.put(name, command); - permissions.put(name, permission); - } - - /** - * Runs the command. - * - * @param sender The sender of the command. - * @param args The arguments passed to the command. - */ - @Override - public void run(CommandSender sender, String[] args) throws CannotExecuteCommandException { - if(args.length == 0) { - runRoot(sender, new String[0]); - } - else { - UHCommand cmd = subcommands.get(args[0]); - if(cmd != null) { - // Allowed? - String permission = permissions.get(args[0]); - if(sender.hasPermission(permission)) { - cmd.run(sender, CommandUtils.getSubcommandArguments(args)); - } - else { - throw new CannotExecuteCommandException(CannotExecuteCommandException.Reason.NOT_ALLOWED); - } - } - else { - runRoot(sender, CommandUtils.getSubcommandArguments(args)); - } - } - } - - /** - * Autocompletes ths command. - * - * @param sender The sender. - * @param args The arguments passed to the command. - * - * @return A list of suggestions. - */ - @Override - public List<String> autocomplete(CommandSender sender, String[] args) { - return null; - } - - /** - * Returns the help of this command. - * - * @param sender The sender. - * - * @return The help. One line per entry in the list. - */ - @Override - public List<String> help(CommandSender sender) { - return null; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/commands/commands/UH.java b/src/main/java/me/azenet/UHPlugin/commands/commands/UH.java deleted file mode 100644 index d873e91..0000000 --- a/src/main/java/me/azenet/UHPlugin/commands/commands/UH.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.commands.commands; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.commands.Command; -import me.azenet.UHPlugin.commands.UHComplexCommand; -import me.azenet.UHPlugin.i18n.I18n; -import org.bukkit.command.CommandSender; - -import java.util.List; - -@Command(name = "uh", permission = "uh") -public class UH extends UHComplexCommand { - - private UHPlugin p; - private I18n i; - - public UH(UHPlugin plugin) { - p = plugin; - i = p.getI18n(); - } - - /** - * This will be executed if this command is called without argument. - * - * @param sender The sender. - */ - @Override - public void runRoot(CommandSender sender, String[] args) { - sender.sendMessage("Hi"); - } - - /** - * Returns the general help for this command. - * <p/> - * <p> - * This help should be a one-line help, as it's displayed as the help - * for the parent commands. - * </p> - * - * @param sender The sender. - * - * @return The help, one line per entry in the list. - */ - @Override - public List<String> helpRoot(CommandSender sender) { - return null; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/EpisodeChangedCause.java b/src/main/java/me/azenet/UHPlugin/events/EpisodeChangedCause.java deleted file mode 100644 index 4e3c287..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/EpisodeChangedCause.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -public enum EpisodeChangedCause { - /** - * The episode changed because the previous episode was finished. - */ - FINISHED, - - /** - * The episode changed because the previous episode was shifted by someone using - * the {@code /uh shift} command. - */ - SHIFTED; -}; diff --git a/src/main/java/me/azenet/UHPlugin/events/TimerEndsEvent.java b/src/main/java/me/azenet/UHPlugin/events/TimerEndsEvent.java deleted file mode 100644 index f4fe146..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/TimerEndsEvent.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import me.azenet.UHPlugin.timers.UHTimer; - -/** - * This event is fired when a timer ends. - * <p> - * It is fired before all the values of the timer are reset. - */ -public final class TimerEndsEvent extends UHEvent { - - private UHTimer timer; - private Boolean timerWasUp = false; - private Boolean restart = false; - - - public TimerEndsEvent(UHTimer timer, Boolean timerUp) { - this.timer = timer; - - this.timerWasUp = timerUp; - } - - /** - * Returns the timer. - * - * @return the timer. - */ - public UHTimer getTimer() { - return timer; - } - - /** - * Returns true if the timer was stopped because it was up. - * - * @return true if the timer was stopped because it was up. - */ - public boolean wasTimerUp() { - return timerWasUp; - } - - /** - * If true, the timer will be restarted. - * - * @param restart true if the timer needs to be restarted. - */ - public void setRestart(boolean restart) { - this.restart = restart; - } - - /** - * Return true if the timer will be restarted. - * - * @param restart true if the timer will be restarted. - * @return - */ - public boolean getRestart() { - return this.restart; - } -} \ No newline at end of file diff --git a/src/main/java/me/azenet/UHPlugin/events/TimerStartsEvent.java b/src/main/java/me/azenet/UHPlugin/events/TimerStartsEvent.java deleted file mode 100644 index e6de8e0..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/TimerStartsEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import me.azenet.UHPlugin.timers.UHTimer; - -/** - * This event is fired when a timer ends. - * - * @author Amaury Carrade - */ -public final class TimerStartsEvent extends UHEvent { - private UHTimer timer; - - public TimerStartsEvent(UHTimer timer) { - this.timer = timer; - } - - /** - * Returns the timer. - * - * @return - */ - public UHTimer getTimer() { - return timer; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHEpisodeChangedEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHEpisodeChangedEvent.java deleted file mode 100644 index ada936d..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHEpisodeChangedEvent.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -/** - * Called when an episode changes. - */ -public class UHEpisodeChangedEvent extends UHEvent { - - private int newEpisode; - private EpisodeChangedCause cause; - private String shifter; - - public UHEpisodeChangedEvent(int newEpisode, EpisodeChangedCause cause, String shifter) { - this.newEpisode = newEpisode; - this.cause = cause; - this.shifter = shifter; - } - - /** - * Returns the new episode. - * - * @return The new episode. - */ - public int getNewEpisode() { - return newEpisode; - } - - /** - * Why the episode changed? - * - * @return The cause. - * - * @see EpisodeChangedCause - */ - public EpisodeChangedCause getCause() { - return cause; - } - - /** - * Returns the name of the shifter (the one that executed the /uh shift command, or "" if - * the episode was shifted because the previous one was finished). - * - * @return The shifter. - */ - public String getShifter() { - return shifter; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHEvent.java deleted file mode 100644 index 4c584bd..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * An UHC Reloaded event - */ -public class UHEvent extends Event { - - private static final HandlerList handlers = new HandlerList(); - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHGameEndsEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHGameEndsEvent.java deleted file mode 100644 index 673e741..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHGameEndsEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import me.azenet.UHPlugin.teams.UHTeam; - -public class UHGameEndsEvent extends UHEvent { - private UHTeam winner; - - public UHGameEndsEvent(UHTeam winner) { - this.winner = winner; - } - - /** - * Returns the last team alive. - * - * @return The team. - */ - public UHTeam getWinnerTeam() { - return winner; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHGameStartsEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHGameStartsEvent.java deleted file mode 100644 index 7e69bf1..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHGameStartsEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -/** - * This event is fired when the UHC game is started. - */ -public class UHGameStartsEvent extends UHEvent { - -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHPlayerDeathEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHPlayerDeathEvent.java deleted file mode 100644 index bc80dfe..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHPlayerDeathEvent.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import org.bukkit.entity.Player; -import org.bukkit.event.entity.PlayerDeathEvent; - -/** - * Fired when a player playing an UHC match is dead. - * <p> - * This event is called before all the action executed on player death (sound, scoreboard updates, etc.). - */ -public class UHPlayerDeathEvent extends UHEvent { - - private Player player; - private PlayerDeathEvent ev; - - public UHPlayerDeathEvent(Player player, PlayerDeathEvent ev) { - this.player = player; - this.ev = ev; - } - - /** - * Returns the dead player. - * @return The player. - */ - public Player getPlayer() { - return player; - } - - /** - * Returns the PlayerDeathEvent under this event. - * @return The PlayerDeathEvent. - */ - public PlayerDeathEvent getPlayerDeathEvent() { - return ev; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHPlayerResurrectedEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHPlayerResurrectedEvent.java deleted file mode 100644 index ba7cd3a..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHPlayerResurrectedEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import org.bukkit.entity.Player; - -/** - * Called when a player is resurrected. - * <p> - * This event is called when: - * <ul> - * <li>the command {@code /uh resurrect <player>} is executed, if the target is online;</li> - * <li>the resurrected player logins, else</li> - * </ul> - * (i.e. when the message “the player is resurrected” is broadcasted). - */ -public class UHPlayerResurrectedEvent extends UHEvent { - - private Player resurrectedPlayer; - - public UHPlayerResurrectedEvent(Player player) { - this.resurrectedPlayer = player; - } - - /** - * Returns the resurrected player. - * - * @return The player. - */ - public Player getPlayer() { - return resurrectedPlayer; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/events/UHTeamDeathEvent.java b/src/main/java/me/azenet/UHPlugin/events/UHTeamDeathEvent.java deleted file mode 100644 index 8f4f80b..0000000 --- a/src/main/java/me/azenet/UHPlugin/events/UHTeamDeathEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.events; - -import me.azenet.UHPlugin.teams.UHTeam; - -/** - * Event fired when the last member of a team die. - */ -public class UHTeamDeathEvent extends UHEvent { - - private UHTeam team; - - public UHTeamDeathEvent(UHTeam team) { - this.team = team; - } - - /** - * Returns the now-dead team. - * - * @return The team. - */ - public UHTeam getTeam() { - return team; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/i18n/I18n.java b/src/main/java/me/azenet/UHPlugin/i18n/I18n.java deleted file mode 100644 index 8db9fd2..0000000 --- a/src/main/java/me/azenet/UHPlugin/i18n/I18n.java +++ /dev/null @@ -1,421 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.i18n; - -import com.google.common.base.Charsets; -import org.bukkit.ChatColor; -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.*; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.logging.Level; - -/** - * This class is used to manage the internationalization of this plugin. - * It is plugin-independent. - * - * @author Amaury Carrade - * @version 1.2 - * @license Mozilla Public License - * - */ -public class I18n { - - private Plugin p = null; - - private String selectedLanguage = null; - private String defaultLanguage = null; - - private Map<String,FileConfiguration> languageSource = new HashMap<String,FileConfiguration>(); - private Map<String,File> languageFile = new HashMap<String,File>(); - private File manifestFile = null; - private FileConfiguration manifest = null; - - /** - * Constructor. - * - * About the storage: - * - the translation files are stored in the directory {PluginDir}/i18n/{languageCode}.yml - * - an additional file, {PluginDir}/i18n/manifest.yml, contains two keys. - * - "languages": this key is a list of the available languages. - * - "version": this key is the version of the plugin (used to update the language files on the disk). - * This needs to be the exact version defined in the plugin.yml file. - * - * Currently, an "en_US" language file is needed. - * Else, if the requested language is not available, a crash will occur when trying to load the en_US language. - * - * @param plugin The plugin. - * @param selectedLanguage The selected language. - * @param defaultLanguage The default language, used when a key is missing or null. - */ - public I18n(Plugin plugin, String selectedLanguage, String defaultLanguage) { - this.p = plugin; - - // Write the manifest - try { - p.saveResource(getLanguageFilePath("manifest"), false); - reloadManifest(); - } catch (IllegalArgumentException e) { - p.getLogger().log(Level.SEVERE, "Unable to read the in-JAR i18n manifest! YOU DOWNLOADED A MALFORMED JAR, PLEASE RE-DOWNLOAD IT.", e); - return; - } - catch (InvalidConfigurationException e) { - p.getLogger().log(Level.SEVERE, "Unable to load a malformed i18n manifest", e); - return; - } - - // The language files need to be written - // and to be overwritten if the plugin was updated (== different version) - writeFilesIfNeeded(); - - this.selectedLanguage = selectedLanguage; - this.defaultLanguage = defaultLanguage; - - if(!isLanguageAvailable(selectedLanguage)) { - if(isLanguageAvailable(getLanguageName(Locale.getDefault()))) { - this.selectedLanguage = getLanguageName(Locale.getDefault()); - } - else { - this.selectedLanguage = "en_US"; - } - p.getLogger().info("The selected language (" + selectedLanguage + ") is not available or not registered in the manifest; using " + this.selectedLanguage + "."); - } - if(!isLanguageAvailable(defaultLanguage)) { - this.defaultLanguage = "en_US"; - p.getLogger().info("The default language (" + defaultLanguage + ") is not available or not registered in the manifest; using en_US."); - } - - try { - this.reloadLanguageFile(this.selectedLanguage); - this.reloadLanguageFile(this.defaultLanguage); - } catch (InvalidConfigurationException e) { - p.getLogger().log(Level.SEVERE, "Unable to load malformed language files (" + this.selectedLanguage + " or " + this.defaultLanguage + ").", e); - return; - } catch (IllegalArgumentException e) { - p.getLogger().log(Level.SEVERE, "Unable to load unregistered language files (" + this.selectedLanguage + " or " + this.defaultLanguage + ").", e); - return; - } catch (FileNotFoundException e) { - p.getLogger().log(Level.SEVERE, "Language file not found (" + this.selectedLanguage + " or " + this.defaultLanguage + ").", e); - return; - } catch (IOException e) { - p.getLogger().log(Level.SEVERE, "I/O exception while loading a language file (" + this.selectedLanguage + " or " + this.defaultLanguage + ").", e); - return; - } - } - - /** - * Constructor. - * With this constructor, the default language is the English one (en_US). - * - * @param plugin The plugin. - * @param selectedLanguage The selected language. - */ - public I18n(Plugin plugin, String selectedLanguage) { - this(plugin, selectedLanguage, "en_US"); - } - - /** - * Constructor. - * With this constructor, the default language is the English one (en_US), and - * the selected language is the one returned by Locale.getDefault(). - * - * @param plugin The plugin. - */ - public I18n(Plugin plugin) { - this(plugin, getLanguageName(Locale.getDefault())); - } - - /** - * Returns the translator of the given language. - * - * @param lang The language. - * @return The translator, or null if not defined. - */ - public String getTranslator(String lang) { - if(this.languageSource.get(lang) == null) { - return null; - } - return this.languageSource.get(lang).getString("author"); - } - - /** - * Returns the selected language. - * - * @return The code of the language (ex. en_US). - */ - public String getSelectedLanguage() { - return this.selectedLanguage; - } - - /** - * Returns the default (fallback) language. - * - * @return The code of the language (ex. en_US). - */ - public String getDefaultLanguage() { - return this.defaultLanguage; - } - - /** - * Returns the translated value associated to a key. - * - * @param key The key. - * @return - */ - public String t(String key) { - // 1) main language available? - if(this.getRawString(key, selectedLanguage) != null) { - return this.replaceStandardKeys(this.getRawString(key, selectedLanguage)); - } - // 2) default language maybe? - else if(this.getRawString(key, defaultLanguage) != null) { - return this.replaceStandardKeys(this.getRawString(key, defaultLanguage)); - } - // 3) Nothing? Returns the key. - else { - return key; - } - } - - /** - * Returns the translated value associated to a key. - * Replaces {0}, {1}, etc. with the other parameters, following the order of these parameters. - * - * @param key The key. - * @param params The additional parameters. - * @return - */ - public String t(String key, String... params) { - int i = 0; - String text = t(key); - - for(String param : params) { - text = text.replace("{" + i + "}", param); - i++; - } - - return text; - } - - /** - * Returns the raw translation stored in the language file. - * - * @param key - * @param lang - * @return - */ - private String getRawString(String key, String lang) { - if(this.languageSource.get(lang) == null) { - return null; - } - return this.languageSource.get(lang).getString("keys." + key); - } - - /** - * Replaces standard keys in the message, like {gold} for the gold color code. - * - * @param text - * @return - */ - private String replaceStandardKeys(String text) { - - return text.replace("{black}", ChatColor.BLACK.toString()) - .replace("{darkblue}", ChatColor.DARK_BLUE.toString()) - .replace("{darkgreen}", ChatColor.DARK_GREEN.toString()) - .replace("{darkaqua}", ChatColor.DARK_AQUA.toString()) - .replace("{darkred}", ChatColor.DARK_RED.toString()) - .replace("{darkpurple}", ChatColor.DARK_PURPLE.toString()) - .replace("{gold}", ChatColor.GOLD.toString()) - .replace("{gray}", ChatColor.GRAY.toString()) - .replace("{darkgray}", ChatColor.DARK_GRAY.toString()) - .replace("{blue}", ChatColor.BLUE.toString()) - .replace("{green}", ChatColor.GREEN.toString()) - .replace("{aqua}", ChatColor.AQUA.toString()) - .replace("{red}", ChatColor.RED.toString()) - .replace("{lightpurple}", ChatColor.LIGHT_PURPLE.toString()) - .replace("{yellow}", ChatColor.YELLOW.toString()) - .replace("{white}", ChatColor.WHITE.toString()) - - .replace("{bold}", ChatColor.BOLD.toString()) - .replace("{strikethrough}", ChatColor.STRIKETHROUGH.toString()) - .replace("{underline}", ChatColor.UNDERLINE.toString()) - .replace("{italic}", ChatColor.ITALIC.toString()) - .replace("{obfuscated}", ChatColor.MAGIC.toString()) - - .replace("{reset}", ChatColor.RESET.toString()) - - .replace("{ce}", ChatColor.RED.toString()) // error - .replace("{cc}", ChatColor.GOLD.toString()) // command - .replace("{ci}", ChatColor.WHITE.toString()) // info - .replace("{cs}", ChatColor.GREEN.toString()) // success - .replace("{cst}", ChatColor.DARK_GRAY.toString()); // status - } - - /** - * Returns the name of the language associated with the given locale. - * <p> - * <code>locale.toString()</code> is not use to avoid a longer name, because the format - * of this method is: - * - * <pre>language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions</pre> - * - * <p> - * Static because I need this in a constructor. - * - * @param locale The locale - * @return The name of the locale, formatted following this scheme: "language_COUNTRY". - */ - private static String getLanguageName(Locale locale) { - return locale.getLanguage() + "_" + locale.getCountry(); - } - - /** - * Returns true if the given language is available, using the manifest. - * - * @param lang The lang. - * @return true if the given language is available. - */ - private boolean isLanguageAvailable(String lang) { - return this.manifest.getList("languages").contains(lang); - } - - /** - * (Re)loads a language file. - * - * @param lang The language to (re)load. - * @throws IllegalArgumentException if the language is not registered. - * @throws FileNotFoundException if the language file does not exists in the server's plugins directory. - * @throws IOException if an I/O problem happen. - * @throws InvalidConfigurationException if the language file is malformed (not a valid YAML file). - */ - private void reloadLanguageFile(String lang) throws InvalidConfigurationException, IllegalArgumentException, FileNotFoundException, IOException { - lang = this.cleanLanguageName(lang); - - if(!isLanguageAvailable(lang)) { // Unknown language - throw new IllegalArgumentException("The language " + lang + " is not registered"); - } - - if(this.languageFile.get(lang) == null) { - this.languageFile.put(lang, new File(p.getDataFolder() + "/" + getLanguageFilePath(lang))); - } - - - // The YAML configuration is loaded using a Reader, to specify the encoding to be used, - // to be able to force UTF-8. - // An InputStream of the language file is needed for this. - InputStream languageFileInputStream = null; - languageFileInputStream = languageFile.get(lang).toURI().toURL().openConnection().getInputStream(); - this.languageSource.put(lang, YamlConfiguration.loadConfiguration(new InputStreamReader(languageFileInputStream, Charsets.UTF_8))); - - - // Default config - try { - Reader defaultLanguageFile = new InputStreamReader(p.getResource(getLanguageFilePath(lang)), Charsets.UTF_8); - if(defaultLanguageFile != null) { - YamlConfiguration defaultLanguageSource = YamlConfiguration.loadConfiguration(defaultLanguageFile); - this.languageSource.get(lang).setDefaults(defaultLanguageSource); - } - } catch(NullPointerException ignored) { - // No "default" translation file available: user-only language file. - } - } - - /** - * Reloads the manifest. - * @return - */ - private void reloadManifest() throws InvalidConfigurationException { - if(manifestFile == null) { - manifestFile = new File(p.getDataFolder() + "/" + this.getLanguageFilePath("manifest")); - } - - manifest = YamlConfiguration.loadConfiguration(manifestFile); - } - - /** - * Writes the language files and the manifest to the disk if needed. - * The files are written if they are not already written of if the version changed. - */ - private void writeFilesIfNeeded() { - // Files already written? - File test = new File(p.getDataFolder().getAbsolutePath() + "/" + this.getLanguageFilePath("en_US")); - if(!test.exists()) { // Files not written - writeLanguageFiles(false); - } - else { - // Update needed? - if(manifest != null) { - if(!manifest.getString("version").equals(p.getDescription().getVersion())) { - writeLanguageFiles(true); - p.saveResource(getLanguageFilePath("manifest"), true); - } - } - } - } - - /** - * Writes the language files to the disk, on the {PluginFolder}/i18n/ directory. - * <p> - * (The manifest is not written here, but in the {@link #I18n(Plugin, String, String) constructor}, - * because it is needed here.) - * - * @param overwrite If true, the language files will be overwritten. - */ - private void writeLanguageFiles(boolean overwrite) { - // Normal language files - for(Object lang : manifest.getList("languages")) { - if(lang != null && lang instanceof String && !((String) lang).isEmpty()) { - try { - if(overwrite) p.getLogger().log(Level.INFO, "Updating the language file for " + lang + "..."); - else p.getLogger().log(Level.INFO, "Writing the language file for " + lang + "..."); - - p.saveResource(getLanguageFilePath((String) lang), overwrite); - } catch(IllegalArgumentException e) { - p.getLogger().severe("Unable to load the language file for " + lang + ": the file does not exists."); - } - } - } - } - - /** - * Returns a cleaned version of a language name. - * - * @param lang - * @return - */ - private String cleanLanguageName(String lang) { - return lang.replace(' ', '_'); - } - - /** - * Returns the location of the language file inside the data folder, for the given language. - * - * @param lang - * @return - */ - private String getLanguageFilePath(String lang) { - return "i18n/" + lang + ".yml"; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/integration/UHDynmapIntegration.java b/src/main/java/me/azenet/UHPlugin/integration/UHDynmapIntegration.java deleted file mode 100644 index 9726941..0000000 --- a/src/main/java/me/azenet/UHPlugin/integration/UHDynmapIntegration.java +++ /dev/null @@ -1,263 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.integration; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.teams.TeamColor; -import me.azenet.UHPlugin.teams.UHTeam; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.dynmap.DynmapAPI; -import org.dynmap.markers.Marker; -import org.dynmap.markers.MarkerAPI; -import org.dynmap.markers.MarkerIcon; -import org.dynmap.markers.MarkerSet; - -public class UHDynmapIntegration { - - private UHPlugin p = null; - private I18n i = null; - private DynmapAPI api = null; - private MarkerAPI markerAPI = null; - private MarkerSet markerSet = null; - - public UHDynmapIntegration(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - - Plugin apiTest = Bukkit.getServer().getPluginManager().getPlugin("dynmap"); - if(apiTest == null || !apiTest.isEnabled()) { - p.getLogger().warning("Dynmap is not present, so the integration was disabled."); - return; - } - - this.api = (DynmapAPI) apiTest; - - markerAPI = api.getMarkerAPI(); - if (markerAPI == null) { - p.getLogger().warning("Dynmap is available, but the markers API is not. The integration was disabled."); - return; - } - - - // All is good, let's integrate. - initDynmapIntegration(); - - p.getLogger().info("Successfully hooked into Dynmap."); - } - - private void initDynmapIntegration() { - - markerSet = markerAPI.getMarkerSet("uhplugin.markerset"); - - if(markerSet == null) { - markerSet = markerAPI.createMarkerSet("uhplugin.markerset", "UltraHardcore", null, false); - } - else { - markerSet.setMarkerSetLabel("UltraHardcore"); - } - } - - public void shutdownDynmapIntegration() { - if(isDynmapIntegrationEnabled()) { - markerSet.deleteMarkerSet(); - } - } - - public boolean isDynmapIntegrationEnabled() { - return !(this.api == null); - } - - public DynmapAPI getDynmapAPI() { - return api; - } - - public MarkerAPI getDynmapMarkerAPI() { - return markerAPI; - } - - /** Death locations **/ - - /** - * Displays the death location of the given player. - * - * @param player The player. - */ - public void showDeathLocation(Player player) { - if(!isDynmapIntegrationEnabled()) { - return; - } - - if(!p.getConfig().getBoolean("dynmap.showDeathLocations")) { - return; - } - - if(!p.getGameManager().hasDeathLocation(player)) { - return; - } - - Location deathPoint = p.getGameManager().getDeathLocation(player); - - String markerID = getDeathMarkerName(player); - String markerLabel = i.t("dynmap.markerLabelDeath", player.getName()); - MarkerIcon icon = markerAPI.getMarkerIcon("skull"); - - Marker marker = markerSet.createMarker(markerID, markerLabel, true, deathPoint.getWorld().getName(), deathPoint.getX(), deathPoint.getY(), deathPoint.getZ(), icon, false); - if(marker == null) { - p.getLogger().warning("Unable to create marker " + markerID); - } - } - - /** - * Hides the death location of the given player. - * - * @param player The player. - */ - public void hideDeathLocation(Player player) { - if(!isDynmapIntegrationEnabled()) { - return; - } - - if(!p.getConfig().getBoolean("dynmap.showDeathLocations")) { - return; - } - - Marker marker = markerSet.findMarker(getDeathMarkerName(player)); - if(marker != null) { - marker.deleteMarker(); - } - } - - /** - * Returns the internal ID of the marker of the death point of the given player. - * - * @param player The player. - * @return The ID. - */ - private String getDeathMarkerName(Player player) { - return "uhplugin.death." + player.getName(); - } - - - - /** Spawn locations **/ - - /** - * Displays the spawn point of the given team. - * - * @param team The team. - * @param spawnPoint The location of the spawn point. - */ - public void showSpawnLocation(UHTeam team, Location spawnPoint) { - if(!isDynmapIntegrationEnabled()) { - return; - } - - if(!p.getConfig().getBoolean("dynmap.showSpawnLocations")) { - return; - } - - // Let's try to find the best icon - // Available flags: - // redflag, orangeflag, yellowflag, greenflag, blueflag, purpleflag, pinkflag, pirateflag (black) - // Ref. https://github.com/webbukkit/dynmap/wiki/Using-markers - - MarkerIcon icon = null; - - TeamColor teamColor = team.getColor(); - if(teamColor == null) { - teamColor = TeamColor.GREEN; // green flags for solo games without colors - } - - switch(teamColor) { - case BLUE: - case DARK_BLUE: - case AQUA: - case DARK_AQUA: - icon = markerAPI.getMarkerIcon("blueflag"); - break; - - case GREEN: - case DARK_GREEN: - icon = markerAPI.getMarkerIcon("greenflag"); - break; - - case GOLD: - icon = markerAPI.getMarkerIcon("orangeflag"); - break; - - case YELLOW: - icon = markerAPI.getMarkerIcon("yellowflag"); - break; - - case RED: - case DARK_RED: - icon = markerAPI.getMarkerIcon("redflag"); - break; - - case DARK_PURPLE: - icon = markerAPI.getMarkerIcon("purpleflag"); - break; - - case LIGHT_PURPLE: - icon = markerAPI.getMarkerIcon("pinkflag"); - break; - - case BLACK: - case DARK_GRAY: - case GRAY: - icon = markerAPI.getMarkerIcon("pirateflag"); - break; - - case WHITE: // There is nothing better than pink I think... - default: - icon = markerAPI.getMarkerIcon("pinkflag"); - break; - } - - String markerID = getSpawnMarkerName(team); - String markerLabel = null; - if(p.getGameManager().isGameWithTeams()) { - markerLabel = i.t("dynmap.markerLabelSpawn", team.getName()); - } - else { - markerLabel = i.t("dynmap.markerLabelSpawnNoTeam", team.getName()); - } - - Marker marker = markerSet.createMarker(markerID, markerLabel, true, spawnPoint.getWorld().getName(), spawnPoint.getX(), spawnPoint.getY(), spawnPoint.getZ(), icon, false); - - if(marker == null) { - p.getLogger().warning("Unable to create marker " + markerID); - } - } - - /** - * Returns the internal ID of the marker of the spawn point of the given team. - * - * @param team The team. - * @return The ID. - */ - private String getSpawnMarkerName(UHTeam team) { - return "uhplugin.spawn." + team.getName(); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegration.java b/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegration.java deleted file mode 100644 index 8168809..0000000 --- a/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegration.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.integration; - -import com.comphenix.protocol.ProtocolLibrary; -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.listeners.PacketsListener; - - -public class UHProtocolLibIntegration { - - public UHProtocolLibIntegration(UHPlugin p) { - - // The plugin is available if this is called. - - PacketsListener packetsListener = new PacketsListener(p); - - if(p.getConfig().getBoolean("hardcore-hearts.display")) { - ProtocolLibrary.getProtocolManager().addPacketListener(packetsListener); - } - if(p.getConfig().getBoolean("auto-respawn.do")) { - p.getServer().getPluginManager().registerEvents(packetsListener, p); - } - - p.getLogger().info("Successfully hooked into ProtocolLib."); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegrationWrapper.java b/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegrationWrapper.java deleted file mode 100644 index 8a7e42a..0000000 --- a/src/main/java/me/azenet/UHPlugin/integration/UHProtocolLibIntegrationWrapper.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.integration; - -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; - -import java.util.ArrayList; -import java.util.List; - - -public class UHProtocolLibIntegrationWrapper { - - private UHPlugin p = null; - private UHProtocolLibIntegration integration = null; - - public UHProtocolLibIntegrationWrapper(UHPlugin p) { - this.p = p; - - // Needed to avoid a NoClassDefFoundError. - // I don't like this way of doing this, but else, the plugin will not load without ProtocolLib. - - Plugin pl = Bukkit.getServer().getPluginManager().getPlugin("ProtocolLib"); - if(pl != null && pl.isEnabled()) { - try { - integration = new UHProtocolLibIntegration(p); - } catch(NoClassDefFoundError e) { - p.getLogger().warning("ProtocolLib is present but cannot be loaded (outdated?), so the integration was disabled."); - } - } - else { - p.getLogger().warning("ProtocolLib is not present, so the integration was disabled."); - } - } - - /** - * Returns true if ProtocolLib is installed and integrated into the plugin. - * @return - */ - public boolean isProtocolLibIntegrationEnabled() { - return (this.integration != null); - } - - /** - * Checks if there are some enabled option which require ProtocolLib. - * - * @return A list of enabled options which requires ProtocolLib, or null - * if there isn't any enabled option that requires ProtocolLib. - */ - public List<String> isProtocolLibNeeded() { - - ArrayList<String> options = new ArrayList<String>(); - options.add("hardcore-hearts.display"); - options.add("auto-respawn.do"); - - ArrayList<String> enabledOptions = new ArrayList<String>(); - - for(String option : options) { - if(p.getConfig().getBoolean(option)) { - enabledOptions.add(option); - } - } - - if(enabledOptions.size() != 0) { - return enabledOptions; - } - else { - return null; - } - } - - /** - * Returns the wrapped integration. - * - * @return - */ - public UHProtocolLibIntegration getIntegration() { - return integration; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/integration/UHSpectatorPlusIntegration.java b/src/main/java/me/azenet/UHPlugin/integration/UHSpectatorPlusIntegration.java deleted file mode 100644 index 55e37cb..0000000 --- a/src/main/java/me/azenet/UHPlugin/integration/UHSpectatorPlusIntegration.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.integration; - -import com.pgcraft.spectatorplus.SpectateAPI; -import com.pgcraft.spectatorplus.SpectatorPlus; -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; - - -public class UHSpectatorPlusIntegration { - - private UHPlugin p = null; - private SpectatorPlus sp = null; - private SpectateAPI spAPI = null; - - public UHSpectatorPlusIntegration(UHPlugin p) { - this.p = p; - - Plugin spTest = Bukkit.getServer().getPluginManager().getPlugin("SpectatorPlus"); - if(spTest == null || !spTest.isEnabled()) { - this.p.getLogger().warning("SpectatorPlus is not present, so the integration was disabled."); - return; - } - - this.sp = (SpectatorPlus) spTest; - - - try { - Class.forName("com.pgcraft.spectatorplus.SpectateAPI"); - - if(sp.getDescription().getVersion().equals("1.9.1")) { - // The API of SpectatorPlus 1.9.1 was not working. - throw new ClassNotFoundException(); - } - } - catch(ClassNotFoundException e) { - this.p.getLogger().warning("SpectatorPlus is available, but the version you are using is too old."); - this.p.getLogger().warning("This plugin is tested and works with SpectatorPlus 1.9.2 or later. The SpectateAPI is needed."); - - this.sp = null; - return; - } - - - // All is OK, let's integrate. - this.spAPI = sp.getAPI(); - - spAPI.setCompass(true, true); - spAPI.setSpectateOnDeath(true, true); - spAPI.setColouredTabList(false, true); // potential conflict with our scoreboard - - this.p.getLogger().info("Successfully hooked into SpectatorPlus."); - } - - public boolean isSPIntegrationEnabled() { - return !(this.sp == null); - } - - public SpectatorPlus getSP() { - return this.sp; - } - - public SpectateAPI getSPAPI() { - return this.spAPI; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/integration/UHWorldBorderIntegration.java b/src/main/java/me/azenet/UHPlugin/integration/UHWorldBorderIntegration.java deleted file mode 100644 index 6577a9f..0000000 --- a/src/main/java/me/azenet/UHPlugin/integration/UHWorldBorderIntegration.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.integration; - -import com.wimbli.WorldBorder.BorderData; -import com.wimbli.WorldBorder.Config; -import com.wimbli.WorldBorder.WorldBorder; -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.MapShape; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.World.Environment; -import org.bukkit.plugin.Plugin; - -public class UHWorldBorderIntegration { - - private UHPlugin p = null; - private WorldBorder wb = null; - - public UHWorldBorderIntegration(UHPlugin p) { - this.p = p; - - Plugin wbTest = Bukkit.getServer().getPluginManager().getPlugin("WorldBorder"); - if(wbTest == null || !wbTest.isEnabled()) { - p.getLogger().warning("WorldBorder is not present, so the integration was disabled."); - return; - } - - this.wb = (WorldBorder) wbTest; - - - try { - Class.forName("com.wimbli.WorldBorder.BorderData"); - Class.forName("com.wimbli.WorldBorder.Config"); - } - catch(ClassNotFoundException e) { - p.getLogger().warning("WorldBorder is available, but the version you are using is too old."); - p.getLogger().warning("This plugin is tested and works with WorldBorder 1.8.0 or later."); - - this.wb = null; - return; - } - - - // All is good, let's integrate. - setupBorders(); - - p.getLogger().info("Successfully hooked into WorldBorder."); - } - - public void setupBorders() { - if(!isWBIntegrationEnabled()) { - return; - } - - /** General configuration **/ - - Config.setPortalRedirection(true); // Because the nether is border-less. - - - /** Overworld border **/ - - World overworld = getOverworld(); - BorderData borderOverworld = wb.getWorldBorder(overworld.getName()); - - if(borderOverworld == null) { // The border needs to be created from scratch - borderOverworld = new BorderData(0, 0, 0); // Random values, overwritten later. - } - - borderOverworld.setShape(p.getBorderManager().getMapShape() == MapShape.CIRCULAR); - - borderOverworld.setX(overworld.getSpawnLocation().getX()); // A border centered on the spawn point - borderOverworld.setZ(overworld.getSpawnLocation().getZ()); - - borderOverworld.setRadius((int) Math.floor(p.getBorderManager().getCheckDiameter()/2)); - - Config.setBorder(overworld.getName(), borderOverworld); - - p.getLogger().info("Overworld border configured using WorldBorder (world \"" + overworld.getName() + "\")."); - - - /** Nether border **/ - - // There is not any border set for the Nether, because WorldBorder handles portal redirection - // if a player rebuild a portal far from the Nether' spawn point. - - } - - /** - * Returns the overworld. - * - * @return the... overworld? - */ - private World getOverworld() { - for(World world : Bukkit.getServer().getWorlds()) { - if(world.getEnvironment() != Environment.NETHER && world.getEnvironment() != Environment.THE_END) { - return world; - } - } - return null; - } - - public boolean isWBIntegrationEnabled() { - return !(this.wb == null); - } - - public WorldBorder getWorldBorder() { - return wb; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/listeners/CraftingListener.java b/src/main/java/me/azenet/UHPlugin/listeners/CraftingListener.java deleted file mode 100644 index e03fd3f..0000000 --- a/src/main/java/me/azenet/UHPlugin/listeners/CraftingListener.java +++ /dev/null @@ -1,289 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.listeners; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.misc.ProTipsSender; -import me.azenet.UHPlugin.recipes.RecipesManager; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.Event.Result; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.inventory.InventoryType.SlotType; -import org.bukkit.event.inventory.PrepareItemCraftEvent; -import org.bukkit.inventory.*; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.HashSet; - -public class CraftingListener implements Listener { - private UHPlugin p = null; - private I18n i = null; - - public CraftingListener(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - } - - - /** - * Used to: - * - prevent items to be crafted; - * - send a ProTip containing the craft to use, if an error occurred; - * - add a lure to the golden apples crafted from a head; - * - keep the name of the item when the anti-lore craft is used. - * - * @param ev - */ - @EventHandler - public void onPreCraftEvent(PrepareItemCraftEvent ev) { - Recipe recipe = ev.getRecipe(); - - if(recipe == null) { - return; - } - - /** Prevents items to be crafted **/ - - if(!p.getRecipesManager().isRecipeAllowed(recipe)) { - ev.getInventory().setResult(new ItemStack(Material.AIR)); - - // ProTips - final String failedRecipe = p.getRecipesManager().getLastFailedRecipe(); - final Player player = (Player) ev.getViewers().get(0); // crafting inventory: only one viewer in all cases. - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - switch(failedRecipe) { - case RecipesManager.RECIPE_COMPASS: - switch(p.getRecipesManager().getCompassRecipeType()) { - case RecipesManager.COMPASS_EASY: - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_CRAFT_COMPASS_EASY); - break; - case RecipesManager.COMPASS_MEDIUM: - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_CRAFT_COMPASS_MEDIUM); - break; - case RecipesManager.COMPASS_HARD: - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_CRAFT_COMPASS_HARD); - break; - } - - break; - - case RecipesManager.RECIPE_GLISTERING_MELON: - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_CRAFT_GLISTERING_MELON); - break; - - case RecipesManager.RECIPE_ENCHANTED_GOLDEN_APPLE: - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_CRAFT_NO_ENCHANTED_GOLDEN_APPLE); - break; - } - } - }, 40L); - - return; - } - - - /** Adds a lore to the golden apples crafted from a head **/ - - ItemStack loreResult = p.getRecipesManager().addLore(recipe, ev.getInventory()); - if(loreResult != null) { - ev.getInventory().setResult(loreResult); - return; - } - - - /** The lore remover don't change the name of the item **/ - - ItemStack keepNameResult = p.getRecipesManager().keepNameOnLoreRemover(recipe, ev.getInventory()); - if(keepNameResult != null) { - ev.getInventory().setResult(keepNameResult); - return; - } - } - - - /** - * - Workaround to fix the crafting grid being not updated when the item is taken - * from the grid. - * <p> - * - Prevents an apple to be renamed to/from the name of an head apple. - * - * (In vanilla clients, it is not possible to rename an apple to that name because of the - * ChatColor.RESET before, but some modded clients allows the player to write §r.) - * - * (Thanks to Zelnehlun on BukkitDev.) - * <p> - * - Crafts the special compass (“semi-shapeless” recipe). - * - * @param ev - */ - @EventHandler(ignoreCancelled = true) - public void onInventoryClick(final InventoryClickEvent ev) { - if(ev.getWhoClicked() instanceof Player) { // Just in case - final Inventory inventory = ev.getInventory(); - - /** Workaround to fix the crafting grid being not updated when the item is taken - from the grid. **/ - if(inventory instanceof CraftingInventory && ev.getSlotType() == SlotType.RESULT) { - p.getServer().getScheduler().runTaskLater(p, new BukkitRunnable() { - - @Override - public void run() { - for(HumanEntity viewer : ev.getViewers()) { - if(viewer instanceof Player) { - ((Player) viewer).updateInventory(); - } - } - } - }, 1L); - } - - - /** Allows any shape for the loots in the compass recipe. **/ - - if(inventory instanceof CraftingInventory) { - - // This is ran one tick after the click because when the event is fired, the inventory - // object is not updated, and so the result of the isValidCompassResult is invalid. - - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - if(p.getRecipesManager().isValidCompassRecipe(((CraftingInventory) inventory).getMatrix())) { - - // Puts the compass in the result slot - if(ev.getSlotType() == SlotType.CRAFTING) { - ((CraftingInventory) inventory).setResult(new ItemStack(Material.COMPASS)); - ev.setResult(Result.ALLOW); - - ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed - } - - // Consumes the materials in the crafting grid. - // Because this is not an "official" recipe, we need to do that manually. - else if(ev.getSlotType() == SlotType.RESULT) { - int index = 1; - for(ItemStack stack : ((CraftingInventory) inventory).getMatrix()) { - if(stack == null) continue; - - if(stack.getAmount() != 1) { - stack.setAmount(stack.getAmount() - 1); - inventory.setItem(index, stack); - } - else { - inventory.setItem(index, new ItemStack(Material.AIR)); - } - - index++; - } - - ev.setCurrentItem(new ItemStack(Material.COMPASS)); - ev.setResult(Result.ALLOW); - - ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed - } - - return; - } - } - - }, 1L); - } - - - /** Prevent an apple to be renamed to/from the name of an head apple. **/ - - else if(inventory instanceof AnvilInventory) { - InventoryView view = ev.getView(); - int rawSlot = ev.getRawSlot(); - - if(rawSlot == view.convertSlot(rawSlot)) { // ensure we are talking about the upper inventory - if(rawSlot == 2) { // "result" slot - ItemStack item = ev.getCurrentItem(); - if(item != null) { // result slot non empty - ItemMeta meta = item.getItemMeta(); - - HashSet<String> prohibited = new HashSet<String>(); - - prohibited.add(ChatColor.RESET + i.t("craft.goldenApple.nameGoldenAppleFromHeadNormal")); - prohibited.add(ChatColor.RESET + i.t("craft.goldenApple.nameGoldenAppleFromHeadNotch")); - - // It is possible that the client filters the name of the golden apple in the anvil UI, - // removing all §. - for(String prohibition : new HashSet<String>(prohibited)) { - prohibited.add(prohibition.replace("§", "")); - } - - - // An item can't be renamed to the name of a golden head - if(meta != null && meta.hasDisplayName()) { - if(prohibited.contains(meta.getDisplayName())) { - ev.setCancelled(true); // nope nope nope - } - } - - // A golden head can't be renamed to any other name - if(view.getItem(0) != null) { // slot 0 = first slot - ItemMeta metaOriginal = view.getItem(0).getItemMeta(); - - if(metaOriginal != null && metaOriginal.hasDisplayName()) { - if(prohibited.contains(metaOriginal.getDisplayName())) { - ev.setCancelled(true); - } - } - } - } - } - } - } - } - } - - - /** - * Used to craft the special compass (“semi-shapeless” recipe). - * - * @param ev - */ - @EventHandler(ignoreCancelled = true) - public void onInventoryDrag(final InventoryDragEvent ev) { - if(ev.getInventory() instanceof CraftingInventory) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - if(p.getRecipesManager().isValidCompassRecipe(((CraftingInventory) ev.getInventory()).getMatrix())) { - ((CraftingInventory) ev.getInventory()).setResult(new ItemStack(Material.COMPASS)); - ((Player) ev.getWhoClicked()).updateInventory(); // deprecated but needed - } - } - }, 1L); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/listeners/FreezerListener.java b/src/main/java/me/azenet/UHPlugin/listeners/FreezerListener.java deleted file mode 100644 index 6bea07e..0000000 --- a/src/main/java/me/azenet/UHPlugin/listeners/FreezerListener.java +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.listeners; - -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.*; -import org.bukkit.event.player.PlayerMoveEvent; - -public class FreezerListener implements Listener { - - private UHPlugin p = null; - - public FreezerListener(UHPlugin p) { - this.p = p; - } - - - /** - * Used to prevent frozen players to break blocks. - * - * @param ev - */ - @EventHandler - public void onBlockBreakEvent(final BlockBreakEvent ev) { - if (p.getFreezer().isPlayerFrozen(ev.getPlayer())) { - ev.setCancelled(true); - } - } - - - /** - * Used to prevent frozen players to place blocks. - * - * @param ev - */ - @EventHandler - public void onBlockPlaceEvent(final BlockPlaceEvent ev) { - if (p.getFreezer().isPlayerFrozen(ev.getPlayer())) { - ev.setCancelled(true); - } - } - - - /** - * Used to freeze the players. - * - * @param ev - */ - @EventHandler - public void onPlayerMove(PlayerMoveEvent ev) { - p.getFreezer().freezePlayerIfNeeded(ev.getPlayer(), ev.getFrom(), ev.getTo()); - } - - - /** - * Used to prevent the bows to be used while in global freeze mode. - * - * @param ev - */ - @EventHandler - public void onEntityShoot(EntityShootBowEvent ev) { - if((ev.getEntity() instanceof Player && p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) - || p.getFreezer().getGlobalFreezeState()) { - - ev.setCancelled(true); - - // If a shoot from a player is cancelled, the arrow seems to be - // consumed in the player' screen. - // The inventory needs to be updated for the arrow to "come back". - if(ev.getEntity() instanceof Player) { - ((Player) ev.getEntity()).updateInventory(); - } - } - } - - - /** - * Used to prevent items from despawning if the game is frozen. - * - * @param ev - */ - @EventHandler - public void onItemDespawn(ItemDespawnEvent ev) { - if(p.getFreezer().getGlobalFreezeState()) { - ev.setCancelled(true); - } - } - - - /** - * Used to freeze the mobs spawning while the game is frozen. - * @param ev - */ - @EventHandler - public void onEntitySpawn(CreatureSpawnEvent ev) { - if(p.getFreezer().getGlobalFreezeState() && ev.getEntity() instanceof Creature) { - p.getFreezer().freezeCreature((Creature) ev.getEntity(), true); - } - } - - - /** - * Used to disable any damages if the player is frozen. - * - * @param ev - */ - @EventHandler - public void onEntityDamage(final EntityDamageEvent ev) { - if (ev.getEntity() instanceof Player) { - if (p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) { - ev.setCancelled(true); - } - } - } - - /** - * Used to cancel any food loss (but the players can still eat). - * - * @param ev - */ - @EventHandler - public void onFoodUpdate(FoodLevelChangeEvent ev) { - if(p.getFreezer().isPlayerFrozen((Player) ev.getEntity())) { - if(ev.getFoodLevel() < ((Player) ev.getEntity()).getFoodLevel()) { - ev.setCancelled(true); - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/listeners/GameListener.java b/src/main/java/me/azenet/UHPlugin/listeners/GameListener.java deleted file mode 100644 index 28a9bec..0000000 --- a/src/main/java/me/azenet/UHPlugin/listeners/GameListener.java +++ /dev/null @@ -1,664 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.listeners; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.events.*; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.misc.ProTipsSender; -import me.azenet.UHPlugin.misc.RuntimeCommandsExecutor; -import me.azenet.UHPlugin.teams.UHTeam; -import me.azenet.UHPlugin.utils.UHSound; -import org.bukkit.*; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.*; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; -import org.bukkit.event.player.*; -import org.bukkit.event.player.PlayerLoginEvent.Result; -import org.bukkit.event.server.ServerListPingEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.List; -import java.util.UUID; - -public class GameListener implements Listener { - - private UHPlugin p = null; - private I18n i = null; - - public GameListener(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - } - - - /** - * Used to: - * - call events (UHPlayerDeathEvent, UHTeamDeathEvent, UHGameEndsEvent); - * - play the death sound; - * - update the scoreboard; - * - kick the player (if needed); - * - broadcast a team-death message (if needed); - * - highlight the death message in the console; - * - increase visibility of the death message (if needed); - * - drop the skull of the dead player (if needed); - * - send a ProTip to the killer about the "golden heads" (if needed); - * - update the number of alive players/teams; - * - save the location of the death of the player, to allow a teleportation later; - * - show the death location on the dynmap (if needed); - * - give XP to the killer (if needed); - * - notify the player about the possibility of respawn if hardcore hearts are enabled; - * - update the MOTD if needed; - * - disable the team-chat-lock if needed. - * - * @param ev - */ - @EventHandler - public void onPlayerDeath(final PlayerDeathEvent ev) { - // This needs to be executed only if the player die as a player, not a spectator. - // Also, the game needs to be started. - if(p.getGameManager().isPlayerDead(ev.getEntity()) || !p.getGameManager().isGameStarted()) { - return; - } - - p.getServer().getPluginManager().callEvent(new UHPlayerDeathEvent(ev.getEntity(), ev)); - - // Plays sound. - p.getGameManager().getDeathSound().broadcast(); - - // Send lightning strike if needed. - if(p.getConfig().getBoolean("death.announcements.lightning-strike")) { - ev.getEntity().getLocation().getWorld().strikeLightningEffect(ev.getEntity().getLocation()); - } - - // Removes the player from the alive players. - this.p.getGameManager().addDead(ev.getEntity()); - - // Kicks the player if needed. - if (this.p.getConfig().getBoolean("death.kick.do", true)) { - Bukkit.getScheduler().runTaskLater(this.p, new BukkitRunnable() { - - @Override - public void run() { - ev.getEntity().kickPlayer(i.t("death.kickMessage")); - } - }, 20L * this.p.getConfig().getInt("death.kick.time", 30)); - } - - // Drops the skull of the player. - if(p.getConfig().getBoolean("death.head.drop")) { - if(!p.getConfig().getBoolean("death.head.pvpOnly") - || (p.getConfig().getBoolean("death.head.pvpOnly") && ev.getEntity().getKiller() != null && ev.getEntity().getKiller() instanceof Player)) { - Location l = ev.getEntity().getLocation(); - try { - ItemStack skull = new ItemStack(Material.SKULL_ITEM, 1, (short) SkullType.PLAYER.ordinal()); - SkullMeta skullMeta = (SkullMeta) skull.getItemMeta(); - skullMeta.setOwner(((Player)ev.getEntity()).getName()); - skullMeta.setDisplayName(ChatColor.RESET + ((Player)ev.getEntity()).getName()); - skull.setItemMeta(skullMeta); - l.getWorld().dropItem(l, skull); - - // Protip - if(ev.getEntity().getKiller() instanceof Player) { - final Player killer = (Player) ev.getEntity().getKiller(); - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - p.getProtipsSender().sendProtip(killer, ProTipsSender.PROTIP_CRAFT_GOLDEN_HEAD); - } - }, 200L); - } - - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - // Give XP to the killer (if needed) - if(p.getConfig().getInt("death.give-xp-to-killer.levels") > 0) { - Entity killer = ev.getEntity().getKiller(); - if(killer != null && killer instanceof Player) { - - boolean inSameTeam = p.getTeamManager().inSameTeam(ev.getEntity(), (Player) killer); - boolean onlyOtherTeam = p.getConfig().getBoolean("death.give-xp-to-killer.onlyOtherTeam"); - - if((onlyOtherTeam && !inSameTeam) || !onlyOtherTeam) { - ((Player) killer).giveExpLevels(p.getConfig().getInt("death.give-xp-to-killer.levels")); - } - } - } - - // Sends a team-death message & event if needed. - final UHTeam team = p.getTeamManager().getTeamForPlayer((Player) ev.getEntity()); - if(team != null) { - boolean isAliveTeam = false; - - for(UUID playerID : team.getPlayersUUID()) { - if(!p.getGameManager().isPlayerDead(playerID)) { - isAliveTeam = true; - break; - } - } - - if(!isAliveTeam) { - p.getServer().getPluginManager().callEvent(new UHTeamDeathEvent(team)); - - if(p.getConfig().getBoolean("death.messages.notifyIfTeamHasFallen", false)) { - // Used to display this message after the death message. - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - String format = ChatColor.translateAlternateColorCodes('&', p.getConfig().getString("death.messages.teamDeathMessagesFormat", "")); - p.getServer().broadcastMessage(i.t("death.teamHasFallen", format, team.getDisplayName() + format)); - } - }, 1L); - } - } - } - - // Highlights the death message in the console - p.getServer().getConsoleSender().sendMessage(ChatColor.GOLD + "-- Death of " + ev.getEntity().getDisplayName() + ChatColor.GOLD + " (" + ev.getDeathMessage() + ") --"); - - // Customizes the death message - String dmFormat = ChatColor.translateAlternateColorCodes('&', p.getConfig().getString("death.messages.deathMessagesFormat", "")); - String deathMessage = dmFormat + ev.getDeathMessage(); - deathMessage = deathMessage.replace(ev.getEntity().getName(), ev.getEntity().getDisplayName() + dmFormat); - if(ev.getEntity().getKiller() != null) { - deathMessage = deathMessage.replace(ev.getEntity().getKiller().getName(), ev.getEntity().getKiller().getDisplayName() + dmFormat); - } - ev.setDeathMessage(deathMessage); - - // Saves the location of the death - p.getGameManager().addDeathLocation(ev.getEntity(), ev.getEntity().getLocation()); - - // Shows the death location on the dynmap - p.getDynmapIntegration().showDeathLocation(ev.getEntity()); - - // Is the game ended? If so, we need to call an event. - if(p.getGameManager().isGameRunning() && p.getGameManager().getAliveTeamsCount() == 1) { - p.getGameManager().setGameFinished(true); - - // There's only one team alive, so the winner team is the first one. - p.getServer().getPluginManager().callEvent(new UHGameEndsEvent(p.getGameManager().getAliveTeams().iterator().next())); - } - - // Notifies the player about the possibility of respawn if hardcore hearts are enabled - if(p.getConfig().getBoolean("hardcore-hearts.display") && p.getProtocolLibIntegrationWrapper().isProtocolLibIntegrationEnabled() && p.getConfig().getBoolean("hardcore-hearts.respawnMessage")) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - ev.getEntity().sendMessage(i.t("death.canRespawn")); - } - }, 2L); - } - - // Disables the team-chat-lock if needed - if(p.getConfig().getBoolean("teams-options.teamChat.disableLockOnDeath")) { - if(p.getTeamChatManager().isTeamChatEnabled(ev.getEntity())) { - p.getTeamChatManager().toggleChatForPlayer(ev.getEntity()); - } - } - } - - - /** - * Used to disable all damages if the game is not started. - * - * @param ev - */ - @EventHandler - public void onEntityDamage(final EntityDamageEvent ev) { - if (ev.getEntity() instanceof Player) { - if (!p.getGameManager().isTakingDamage()) { - ev.setCancelled(true); - } - } - } - - - /** - * Used to prevent the life to be gained with food. - * - * @param ev - */ - @EventHandler - public void onEntityRegainHealth(EntityRegainHealthEvent ev) { - if (ev.getRegainReason() == RegainReason.SATIATED) { - ev.setCancelled(true); - } - } - - - /** - * Used to prevent the food level from dropping if the game has not started. - * - * @param ev - */ - @EventHandler - public void onFoodUpdate(FoodLevelChangeEvent ev) { - if(!p.getGameManager().isGameRunning()) { - if(ev.getEntity() instanceof Player) { - ((Player) ev.getEntity()).setFoodLevel(20); - ((Player) ev.getEntity()).setSaturation(20f); - } - - ev.setCancelled(true); - } - } - - /** - * Used to cancel the spawn of the creatures if the game is not started. - * <p> - * We don't use the peaceful difficulty for that because it causes bugs with Minecraft 1.8 - * (the difficulty is not correctly updated client-side when the game starts). - * - * @param ev - */ - @EventHandler - public void onCreatureSpawn(CreatureSpawnEvent ev) { - if(!p.getGameManager().isGameStarted() - && (ev.getSpawnReason() == SpawnReason.NATURAL - || ev.getSpawnReason() == SpawnReason.NETHER_PORTAL - || ev.getSpawnReason() == SpawnReason.LIGHTNING - || ev.getSpawnReason() == SpawnReason.SPAWNER)) { - - switch(ev.getEntityType()) { - case ZOMBIE: - case CREEPER: - case SKELETON: - case SPIDER: - case ENDERMAN: - case BLAZE: - case CAVE_SPIDER: - case GHAST: - case SILVERFISH: - case SLIME: - case WITCH: - ev.setCancelled(true); - break; - - default: - break; - } - } - } - - - /** - * Used to display our custom state-based MOTD (if needed). - * @param ev - */ - @EventHandler - public void onServerListPing(ServerListPingEvent ev) { - if(p.getMOTDManager().isEnabled()) { - ev.setMotd(p.getMOTDManager().getCurrentMOTD()); - } - } - - - /** - * Used to prevent the player to login after his death (if needed). - * - * @param ev - */ - @EventHandler - public void onPlayerLogin(PlayerLoginEvent ev) { - if (p.getGameManager().isGameStarted() - && p.getGameManager().isPlayerDead(ev.getPlayer()) - && !p.getGameManager().isDeadPlayersToBeResurrected(ev.getPlayer()) - && !p.getConfig().getBoolean("death.kick.allow-reconnect", true)) { - - ev.setResult(Result.KICK_OTHER); - ev.setKickMessage(i.t("death.banMessage")); - } - } - - - /** - * Used to: - * - change the gamemode of the player, if the game is not running; - * - teleport the player to the spawn, if the game is not running; - * - update the scoreboard; - * - put a new player in spectator mode if the game is started (following the config); - * - resurrect a player (if the player was offline). - * - * @param ev - */ - @EventHandler(priority=EventPriority.HIGHEST) - public void onPlayerJoin(final PlayerJoinEvent ev) { - if (!this.p.getGameManager().isGameStarted()) { - if(!p.getGameManager().isSlowStartInProgress()) { - // Initialization of the player (teleportation, life, health objective score...). - p.getGameManager().initPlayer(ev.getPlayer()); - - // Scoreboard update - p.getScoreboardManager().addPlayerBeforeStart(); - - // Teams selector. - if(p.getConfig().getBoolean("teams-options.gui.autoDisplay") && p.getTeamManager().getTeams().size() != 0) { - p.getServer().getScheduler().runTaskLater(p, new Runnable() { - @Override - public void run() { - if(p.getTeamManager().getTeamForPlayer(ev.getPlayer()) == null) { - p.getTeamManager().displayTeamChooserChatGUI(ev.getPlayer()); - } - } - }, 20l * p.getConfig().getInt("teams-options.gui.delay")); - } - } - else { - // Without that the player will be kicked for flying. - ev.getPlayer().setAllowFlight(true); - ev.getPlayer().setFlying(true); - } - } - - // Mainly useful on the first join. - p.getScoreboardManager().setScoreboardForPlayer(ev.getPlayer()); - - // The display name is reset when the player logs off. - p.getTeamManager().colorizePlayer(ev.getPlayer()); - - if(!p.getGameManager().isGameStarted() && ev.getPlayer().hasPermission("uh.*")) { - // A warning to the administrators if WorldBorder is not present. - if(!p.getWorldBorderIntegration().isWBIntegrationEnabled()) { - ev.getPlayer().sendMessage(i.t("load.WBNotInstalled1")); - ev.getPlayer().sendMessage(i.t("load.WBNotInstalled2")); - ev.getPlayer().sendMessage(i.t("load.WBNotInstalled3")); - } - - // The same for SpectatorPlus - if(!p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - ev.getPlayer().sendMessage(i.t("load.SPNotInstalled1")); - ev.getPlayer().sendMessage(i.t("load.SPNotInstalled2")); - } - - // The same for ProtocolLib - if(!p.getProtocolLibIntegrationWrapper().isProtocolLibIntegrationEnabled()) { - List<String> enabledOptionsWithProtocolLibNeeded = p.getProtocolLibIntegrationWrapper().isProtocolLibNeeded(); - - if(enabledOptionsWithProtocolLibNeeded != null) { - ev.getPlayer().sendMessage(i.t("load.PLNotInstalled1")); - ev.getPlayer().sendMessage(i.t("load.PLNotInstalled2")); - for(String option : enabledOptionsWithProtocolLibNeeded) { - ev.getPlayer().sendMessage(i.t("load.PLNotInstalledItem", option)); - } - - String pLibDownloadURL = ""; - if(p.getServer().getBukkitVersion().contains("1.7")) { // 1.7.9 or 1.7.10 - pLibDownloadURL = "http://dev.bukkit.org/bukkit-plugins/protocollib/"; - } - else { // 1.8+ - pLibDownloadURL = "http://www.spigotmc.org/resources/protocollib.1997/"; - } - ev.getPlayer().sendMessage(i.t("load.PLNotInstalled3", pLibDownloadURL)); - } - } - } - - // If the player needs to be resurrected... - if(p.getGameManager().isDeadPlayersToBeResurrected(ev.getPlayer())) { - p.getGameManager().resurrectPlayerOnlineTask(ev.getPlayer()); - p.getGameManager().markPlayerAsResurrected(ev.getPlayer()); - } - - // If the player is a new one, the game is started, and the option is set to true... - if(p.getGameManager().isGameRunning() && p.getConfig().getBoolean("spectatorModeWhenNewPlayerJoinAfterStart") - && !p.getGameManager().getAlivePlayers().contains((OfflinePlayer) ev.getPlayer()) - && p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - p.getSpectatorPlusIntegration().getSPAPI().setSpectating(ev.getPlayer(), true); - } - } - - /** - * Used to update the scoreboard before the beginning of the game. - * @param ev - */ - @EventHandler - public void onPlayerLeave(PlayerQuitEvent ev) { - if(!p.getGameManager().isGameStarted()) { - // Scoreboard update - p.getScoreboardManager().removePlayerBeforeStart(); - } - } - - /** - * Used to disable the achievements before the game. - * - * @param ev - */ - @EventHandler - public void onPlayerAchievementAwarded(PlayerAchievementAwardedEvent ev) { - if(!p.getGameManager().isGameStarted() && p.getConfig().getBoolean("achievements.disableAchievementsBeforeStart", true)) { - ev.setCancelled(true); - } - } - - /** - * Used to disable the statistics before the game. - * - * @param ev - */ - @EventHandler - public void onPlayerStatisticIncrement(PlayerStatisticIncrementEvent ev) { - if(!p.getGameManager().isGameStarted() && p.getConfig().getBoolean("statistics.disableStatisticsBeforeStart", true)) { - ev.setCancelled(true); - } - } - - - /** - * Used to prevent players from breaking blocks if the game is not currently running. - * - * @param ev - */ - @EventHandler - public void onBlockBreakEvent(final BlockBreakEvent ev) { - if (!this.p.getGameManager().isGameStarted() && !((Player)ev.getPlayer()).hasPermission("uh.build")) { - ev.setCancelled(true); - } - } - - /** - * Used to prevent players from placing blocks if the game is not currently running. - * - * @param ev - */ - @EventHandler - public void onBlockPlaceEvent(final BlockPlaceEvent ev) { - if (!this.p.getGameManager().isGameStarted() && !((Player)ev.getPlayer()).hasPermission("uh.build")) { - ev.setCancelled(true); - } - } - - - /** - * Used to send the chat to the team-chat if this team-chat is enabled. - * - * @param ev - */ - // Priority LOWEST to be able to cancel the event before all other plugins - @EventHandler(priority=EventPriority.LOWEST) - public void onAsyncPlayerChat(AsyncPlayerChatEvent ev) { - // If the event is asynchronous, the message was sent by a "real" player. - // Else, the message was sent by a plugin (like our /g command, or another plugin), and - // the event is ignored. - if(ev.isAsynchronous()) { - if(p.getTeamChatManager().isTeamChatEnabled(ev.getPlayer())) { - ev.setCancelled(true); - p.getTeamChatManager().sendTeamMessage(ev.getPlayer(), ev.getMessage()); - } - else if(p.getTeamChatManager().isOtherTeamChatEnabled(ev.getPlayer())) { - ev.setCancelled(true); - p.getTeamChatManager().sendTeamMessage(ev.getPlayer(), ev.getMessage(), p.getTeamChatManager().getOtherTeamEnabled(ev.getPlayer())); - } - } - } - - /** - * Used to: - * - update the internal list of running timers; - * - shift the episode if the main timer is up (and restart this main timer); - * - hide an other timer when it is up. - * - * @param ev - */ - @EventHandler - public void onTimerEnds(TimerEndsEvent ev) { - p.getTimerManager().updateStartedTimersList(); - - if(ev.getTimer().equals(p.getTimerManager().getMainTimer())) { - // If this timer is the main one, we shifts an episode. - p.getGameManager().shiftEpisode(); - ev.setRestart(true); - } - else { - p.getScoreboardManager().hideTimer(ev.getTimer()); - } - - if(ev.getTimer().equals(p.getBorderManager().getWarningTimer()) && ev.wasTimerUp()) { - p.getBorderManager().getWarningSender().sendMessage(i.t("borders.warning.timerUp")); - p.getBorderManager().sendCheckMessage(p.getBorderManager().getWarningSender(), p.getBorderManager().getWarningSize()); - } - } - - /** - * Used to: - * - update the internal list of running timers; - * - display a timer when it is started. - * @param ev - */ - @EventHandler - public void onTimerStarts(TimerStartsEvent ev) { - p.getTimerManager().updateStartedTimersList(); - - if(!ev.getTimer().equals(p.getTimerManager().getMainTimer())) { - p.getScoreboardManager().displayTimer(ev.getTimer()); - } - } - - - /** - * Used to broadcast the episode change. - * - * @param ev - */ - @EventHandler - public void onEpisodeChange(UHEpisodeChangedEvent ev) { - String message = null; - if(ev.getCause() == EpisodeChangedCause.SHIFTED) { - message = i.t("episodes.endForced", String.valueOf(ev.getNewEpisode() - 1), ev.getShifter()); - } - else { - message = i.t("episodes.end", String.valueOf(ev.getNewEpisode() - 1)); - } - p.getServer().broadcastMessage(message); - } - - - /** - * Used to: - * - broadcast the beginning of a game, with sound & message; - * - schedule the commands executed after the beginning of the game. - * - * @param ev - */ - @EventHandler - public void onGameStarts(UHGameStartsEvent ev) { - // Start sound - new UHSound(p.getConfig().getConfigurationSection("start.sound")).broadcast(); - - // Broadcast - Bukkit.getServer().broadcastMessage(i.t("start.go")); - - // Commands - p.getRuntimeCommandsExecutor().registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_GAME_START); - - // MOTD - p.getMOTDManager().updateMOTDDuringGame(); - } - - /** - * Used to: - * - broadcast the winner(s) and launch some fireworks if needed, a few seconds later; - * - schedule the commands executed after the end of the game. - * - * @param ev - */ - @EventHandler - public void onGameEnd(UHGameEndsEvent ev) { - if(p.getConfig().getBoolean("finish.auto.do")) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - try { - p.getGameManager().finishGame(); - } catch(IllegalStateException e) { - // The game is not finished (..what?). - e.printStackTrace(); - } - } - }, p.getConfig().getInt("finish.auto.timeAfterLastDeath", 3) * 20L); - } - - // Commands - p.getRuntimeCommandsExecutor().registerCommandsInScheduler(RuntimeCommandsExecutor.AFTER_GAME_END); - - // Updates the MOTD. - p.getMOTDManager().updateMOTDAfterGame(ev.getWinnerTeam()); - } - - - /** - * Used to: - * - disable the spectator mode; - * - hide the death point from the dynmap; - * - broadcast this resurrection to all players; - * - update the MOTD. - * - * @param ev - */ - @EventHandler - public void onPlayerResurrected(UHPlayerResurrectedEvent ev) { - // Spectator mode disabled - if(p.getSpectatorPlusIntegration().isSPIntegrationEnabled()) { - p.getSpectatorPlusIntegration().getSPAPI().setSpectating(ev.getPlayer(), false); - } - - // Death point removed on the dynmap - p.getDynmapIntegration().hideDeathLocation(ev.getPlayer()); - - // All players are notified - this.p.getServer().broadcastMessage(i.t("resurrect.broadcastMessage", ev.getPlayer().getName())); - - // Updates the MOTD. - p.getMOTDManager().updateMOTDDuringGame(); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/listeners/GameplayListener.java b/src/main/java/me/azenet/UHPlugin/listeners/GameplayListener.java deleted file mode 100644 index 08bd83b..0000000 --- a/src/main/java/me/azenet/UHPlugin/listeners/GameplayListener.java +++ /dev/null @@ -1,318 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.listeners; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.task.CancelBrewTask; -import org.bukkit.*; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Ghast; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerItemConsumeEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.event.weather.WeatherChangeEvent; -import org.bukkit.inventory.BrewerInventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.ArrayList; -import java.util.List; - -public class GameplayListener implements Listener { - - private UHPlugin p = null; - private I18n i = null; - - public GameplayListener(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - } - - - /** - * Used to replace ghast tears with gold (if needed). - * - * @param ev - */ - @EventHandler(ignoreCancelled = true) - public void onEntityDeath(EntityDeathEvent ev) { - if (ev.getEntity() instanceof Ghast && p.getConfig().getBoolean("gameplay-changes.replaceGhastTearsWithGold")) { - List<ItemStack> drops = new ArrayList<ItemStack>(ev.getDrops()); - ev.getDrops().clear(); - for (ItemStack i : drops) { - if (i.getType() == Material.GHAST_TEAR) { - ev.getDrops().add(new ItemStack(Material.GOLD_INGOT,i.getAmount())); - } else { - ev.getDrops().add(i); - } - } - } - } - - /** - * Used to prevent the user to get a ghast tear, if forbidden by the config. - * - * @param ev - */ - @EventHandler(ignoreCancelled = true) - public void onPlayerPickupItem(PlayerPickupItemEvent ev) { - if (ev.getItem().getItemStack().getType() == Material.GHAST_TEAR && ev.getPlayer().getGameMode().equals(GameMode.SURVIVAL) && p.getConfig().getBoolean("gameplay-changes.replaceGhastTearsWithGold")) { - ev.setCancelled(true); - } - } - - - /** - * Used to disable power-II potions. - * - * @param ev - */ - @EventHandler - public void onInventoryDrag(InventoryDragEvent ev) { - if(p.getConfig().getBoolean("gameplay-changes.disableLevelIIPotions") && ev.getInventory() instanceof BrewerInventory) { - new CancelBrewTask((BrewerInventory) ev.getInventory(), ev.getWhoClicked()).runTaskLater(p, 1l); - } - } - - /** - * Used to disable power-II potions. - * - * @param ev - */ - @EventHandler - public void onInventoryClick(InventoryClickEvent ev) { - if(p.getConfig().getBoolean("gameplay-changes.disableLevelIIPotions") && ev.getInventory() instanceof BrewerInventory) { - new CancelBrewTask((BrewerInventory) ev.getInventory(), ev.getWhoClicked()).runTaskLater(p, 1l); - } - } - - - /** - * Used to disable enderpearl damages (if needed). - * - * @param ev - */ - @EventHandler(ignoreCancelled = true) - public void onPlayerTeleport(final PlayerTeleportEvent ev) { - if(p.getConfig().getBoolean("gameplay-changes.disableEnderpearlsDamages")) { - if(ev.getCause() == TeleportCause.ENDER_PEARL) { - ev.setCancelled(true); - ev.getPlayer().teleport(ev.getTo(), TeleportCause.PLUGIN); - } - } - } - - - /** - * Used to disable witch spawn (if needed). - * - * @param ev - */ - @EventHandler - public void onCreatureSpawn(CreatureSpawnEvent ev) { - if(ev.getEntityType().equals(EntityType.WITCH)) { - if(p.getConfig().getBoolean("gameplay-changes.witch.disableNaturalSpawn") && ev.getSpawnReason().equals(SpawnReason.NATURAL)) { - ev.setCancelled(true); - } - if(p.getConfig().getBoolean("gameplay-changes.witch.disableLightningSpawn") && ev.getSpawnReason().equals(SpawnReason.LIGHTNING)) { - ev.setCancelled(true); - } - } - } - - - /** - * Used to change the amount of regenerated hearts from a golden apple. - * - * @param ev - */ - @EventHandler - public void onPlayerItemConsume(final PlayerItemConsumeEvent ev) { - - final int TICKS_BETWEEN_EACH_REGENERATION = 50; - final int DEFAULT_NUMBER_OF_HEARTS_REGEN = 4; - final int DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH = 180; - final int REGENERATION_LEVEL_GOLDEN_APPLE = 2; - final int REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE = 5; - - if(ev.getItem().getType() == Material.GOLDEN_APPLE) { - ItemMeta meta = ev.getItem().getItemMeta(); - short dataValue = ev.getItem().getDurability(); - int halfHearts = 0; - int level = 0; - - if(meta.hasDisplayName() - && (meta.getDisplayName().equals(ChatColor.RESET + i.t("craft.goldenApple.nameGoldenAppleFromHeadNormal")) - || meta.getDisplayName().equals(ChatColor.RESET + i.t("craft.goldenApple.nameGoldenAppleFromHeadNotch")))) { - - if(dataValue == 0) { // Normal golden apple from a head - halfHearts = p.getConfig().getInt("gameplay-changes.goldenApple.regeneration.fromNormalHead", DEFAULT_NUMBER_OF_HEARTS_REGEN); - level = REGENERATION_LEVEL_GOLDEN_APPLE; - } - else { // Notch golden apple from a head - halfHearts = p.getConfig().getInt("gameplay-changes.goldenApple.regeneration.fromNotchHead", DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH); - level = REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE; - } - } - else if(dataValue == 0) { // Normal golden apple from an apple - halfHearts = p.getConfig().getInt("gameplay-changes.goldenApple.regeneration.normal", DEFAULT_NUMBER_OF_HEARTS_REGEN); - level = REGENERATION_LEVEL_GOLDEN_APPLE; - } - else { // Notch golden apple from an apple - halfHearts = p.getConfig().getInt("gameplay-changes.goldenApple.regeneration.notch", DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH); - level = REGENERATION_LEVEL_NOTCH_GOLDEN_APPLE; - } - - // Technically, a level-I effect is « level 0 ». - final int realLevel = level - 1; - - - // What is needed to do? - if((dataValue == 0 && halfHearts == DEFAULT_NUMBER_OF_HEARTS_REGEN) - || (dataValue == 1 && halfHearts == DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH)) { - - // Default behavior, nothing to do. - } - else if((dataValue == 0 && halfHearts > DEFAULT_NUMBER_OF_HEARTS_REGEN) - || (dataValue == 1 && halfHearts > DEFAULT_NUMBER_OF_HEARTS_REGEN_NOTCH)) { - - // If the heal needs to be increased, the effect can be applied immediately. - - int duration = ((int) Math.floor(TICKS_BETWEEN_EACH_REGENERATION / (Math.pow(2, realLevel)))) * halfHearts; - - new PotionEffect(PotionEffectType.REGENERATION, duration, realLevel).apply(ev.getPlayer()); - } - else { - // The heal needs to be decreased. - // We can't apply the effect immediately, because the server will just ignore it. - // So, we apply it two ticks later, with one half-heart less (because in two ticks, - // one half-heart is given to the player). - - final int healthApplied = halfHearts - 1; - - Bukkit.getScheduler().runTaskLater(this.p, new BukkitRunnable() { - @Override - public void run() { - // The original, vanilla, effect is removed - ev.getPlayer().removePotionEffect(PotionEffectType.REGENERATION); - - int duration = ((int) Math.floor(TICKS_BETWEEN_EACH_REGENERATION / (Math.pow(2, realLevel)))) * healthApplied; - - new PotionEffect(PotionEffectType.REGENERATION, duration, realLevel).apply(ev.getPlayer()); - } - }, 2l); - } - } - } - - - /** - * Used to update the compass. - * - * @param ev - */ - @SuppressWarnings("deprecation") - @EventHandler - public void onPlayerInteract(PlayerInteractEvent ev) { - if ((ev.getAction() == Action.RIGHT_CLICK_AIR || ev.getAction() == Action.RIGHT_CLICK_BLOCK) && ev.getPlayer().getItemInHand().getType() == Material.COMPASS && p.getConfig().getBoolean("gameplay-changes.compass.enabled") && !p.getGameManager().isPlayerDead(ev.getPlayer())) { - Player player1 = ev.getPlayer(); - - Boolean foundRottenFlesh = false; - for (ItemStack item : player1.getInventory().getContents()) { - if (item != null && item.getType() == Material.ROTTEN_FLESH) { - if (item.getAmount() != 1) { - item.setAmount(item.getAmount()-1); - } - else { - player1.getInventory().removeItem(item); - } - - player1.updateInventory(); - foundRottenFlesh = true; - break; - } - } - - if (!foundRottenFlesh) { - player1.sendMessage(i.t("compass.noRottenFlesh")); - player1.playSound(player1.getLocation(), Sound.STEP_WOOD, 1F, 1F); - return; - } - - Player nearest = null; - Double distance = 99999D; - for (Player player2 : p.getGameManager().getOnlineAlivePlayers()) { - try { - Double calc = player1.getLocation().distance(player2.getLocation()); - - if (calc > 1 && calc < distance) { - distance = calc; - if (!player2.getUniqueId().equals(player1.getUniqueId()) && !p.getTeamManager().inSameTeam(player1, player2)) { - nearest = player2.getPlayer(); - } - } - } catch (Exception ignored) { - - } - } - - if (nearest == null) { - player1.sendMessage(i.t("compass.nothingFound")); - - player1.playSound(player1.getLocation(), Sound.STEP_WOOD, 1F, 1F); - return; - } - - player1.sendMessage(i.t("compass.success")); - player1.setCompassTarget(nearest.getLocation()); - - player1.playSound(player1.getLocation(), Sound.ENDERMAN_TELEPORT, 1F, 1F); - } - } - - - /** - * Used to disable the "bad" weather (aka non-clear weather). - * The weather is initially clear. - * - * @param ev - */ - @EventHandler - public void onWeatherChange(WeatherChangeEvent ev) { - if (!p.getConfig().getBoolean("gameplay-changes.weather")) { - ev.setCancelled(true); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/listeners/PacketsListener.java b/src/main/java/me/azenet/UHPlugin/listeners/PacketsListener.java deleted file mode 100644 index e573a87..0000000 --- a/src/main/java/me/azenet/UHPlugin/listeners/PacketsListener.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.listeners; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.wrappers.EnumWrappers; -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.scheduler.BukkitRunnable; - -import java.lang.reflect.InvocationTargetException; - - -public class PacketsListener extends PacketAdapter implements Listener { - - private UHPlugin p = null; - private ProtocolManager pm = ProtocolLibrary.getProtocolManager(); - - private final PacketContainer respawnPacket; - - public PacketsListener(UHPlugin p) { - // This listener needs to listen on login packets only. - super(p, ListenerPriority.NORMAL, PacketType.Play.Server.LOGIN); - - this.p = p; - - // The packet to send to automatically respawn the player. - respawnPacket = pm.createPacket(PacketType.Play.Client.CLIENT_COMMAND); - respawnPacket.getClientCommands().write(0, EnumWrappers.ClientCommand.PERFORM_RESPAWN); - } - - /** - * Used to present the server as an hardcore server, for the clients to display hardcore hearts. - * - * @param ev - */ - @Override - public void onPacketSending(PacketEvent ev) { - // If its a login packet, write the hardcore flag (first boolean) to true. - if (ev.getPacketType().equals(PacketType.Play.Server.LOGIN)) { - ev.getPacket().getBooleans().write(0, true); - } - } - - /** - * Used to automatically respawn the dead players. - * - * @param ev - */ - @EventHandler - public void onPlayerDeath(final PlayerDeathEvent ev) { - if(p.getConfig().getBoolean("auto-respawn.do")) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - try { - pm.recieveClientPacket(ev.getEntity(), respawnPacket); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - } - }, p.getConfig().getInt("auto-respawn.delay", 6) * 20L); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/misc/Freezer.java b/src/main/java/me/azenet/UHPlugin/misc/Freezer.java deleted file mode 100644 index b321a26..0000000 --- a/src/main/java/me/azenet/UHPlugin/misc/Freezer.java +++ /dev/null @@ -1,253 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.misc; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.listeners.FreezerListener; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.entity.Creature; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.UUID; - -public class Freezer { - - private UHPlugin p = null; - - private boolean isListenerRegistered = false; - private FreezerListener freezerListener = null; - - private Boolean globalFreeze = false; - private ArrayList<UUID> frozenPlayers = new ArrayList<UUID>(); - private HashMap<UUID,Boolean> oldAllowFly = new HashMap<UUID,Boolean>(); - private HashMap<UUID,Boolean> oldFlyMode = new HashMap<UUID,Boolean>(); - - public Freezer(UHPlugin plugin) { - this.p = plugin; - - this.freezerListener = new FreezerListener(p); - } - - - /** - * Freezes a player, if needed. - * The player is blocked inside the block he is currently. - * - * This method is intended to be executed when a player moves. - * - * @param player The player to freeze - * @param from The old position from the PlayerMoveEvent - * @param to The new position from the PlayerMoveEvent - */ - public void freezePlayerIfNeeded(Player player, Location from, Location to) { - if(frozenPlayers.contains(player.getUniqueId())) { - // If the X, Y or Z coordinate of the player change, he needs to be teleported inside the old block. - // The yaw and pitch are conserved, to teleport more smoothly. - if(from.getBlockX() != to.getBlockX() || from.getBlockY() != to.getBlockY() || from.getBlockZ() != to.getBlockZ()) { - player.teleport(new Location(from.getWorld(), from.getBlockX() + 0.5, from.getBlockY(), from.getBlockZ() + 0.5, to.getYaw(), to.getPitch()), TeleportCause.PLUGIN); - } - } - } - - - - /** - * Enables or disables the global freeze of players, mobs, timer. - * - * @param freezed If true the global freeze will be enabled. - * @param showStateInScoreboard If false, the freeze state will not be displayed in the scoreboard. - */ - public void setGlobalFreezeState(Boolean frozen, Boolean showStateInScoreboard) { - this.globalFreeze = frozen; - - if(frozen) { - for(Player player : p.getGameManager().getOnlineAlivePlayers()) { - this.setPlayerFreezeState(player, true); - } - - // Freezes the mobs by applying a Slowness effect. There isn't any EntityMoveEvent, so... - for(World world : p.getServer().getWorlds()) { - for(Entity entity : world.getLivingEntities()) { - if(entity instanceof Creature) { - freezeCreature((Creature) entity, true); - } - } - } - - // Freezes the timers. - p.getTimerManager().pauseAllRunning(true); - } - - else { - // All the online players are listed, not the internal list of frozen players, - // to avoid a ConcurrentModificationException if the iterated list is being emptied. - for(Player player : p.getServer().getOnlinePlayers()) { - if(this.isPlayerFrozen(player)) { - this.setPlayerFreezeState(player, false); - } - } - - // Removes the slowness effect - for(World world : p.getServer().getWorlds()) { - for(Entity entity : world.getLivingEntities()) { - if(entity instanceof Creature) { - freezeCreature((Creature) entity, false); - } - } - } - - // Unfreezes the timers. - p.getTimerManager().pauseAllRunning(false); - p.getScoreboardManager().restartTimers(); - } - - if(showStateInScoreboard || !frozen) { - p.getScoreboardManager().displayFreezeState(); - } - - updateListenerRegistration(); - } - - /** - * Enables or disables the global freeze of players, mobs, timer. - * - * @param freezed If true the global freeze will be enabled. - */ - public void setGlobalFreezeState(Boolean frozen) { - setGlobalFreezeState(frozen, true); - } - - - /** - * Returns the current state of the global freeze. - * - * @return True if the global freeze is enabled. - */ - public boolean getGlobalFreezeState() { - return this.globalFreeze; - } - - /** - * Freezes a player. - * - * @param player The player to freeze. - * @param freezed If true the player will be frozen. If false, unfrozen. - */ - public void setPlayerFreezeState(Player player, Boolean frozen) { - if(frozen && !this.frozenPlayers.contains(player.getUniqueId())) { - this.frozenPlayers.add(player.getUniqueId()); - this.oldAllowFly.put(player.getUniqueId(), player.getAllowFlight()); - this.oldFlyMode.put(player.getUniqueId(), player.isFlying()); - - // Used to prevent the player to be kicked for fly if he was frozen during a fall. - // He is blocked inside his current block anyway. - player.setAllowFlight(true); - } - - if(!frozen && this.frozenPlayers.contains(player.getUniqueId())) { - this.frozenPlayers.remove(player.getUniqueId()); - - player.setFlying(this.oldFlyMode.get(player.getUniqueId())); - player.setAllowFlight(this.oldAllowFly.get(player.getUniqueId())); - - this.oldAllowFly.remove(player.getUniqueId()); - this.oldFlyMode.remove(player.getUniqueId()); - } - - updateListenerRegistration(); - } - - /** - * Returns true if the given player is frozen. - * - * @param player The player to be checked. - * @return true if the given player is frozen. - */ - public boolean isPlayerFrozen(Player player) { - return frozenPlayers.contains(player.getUniqueId()); - } - - /** - * (Un)freezes a creature. - * - * @param creature The creature to freeze. - * @param frozen If true the creature will be frozen. Else... - */ - public void freezeCreature(Creature creature, Boolean frozen) { - if(frozen) { - // Freezes the creature for about 68 years. - creature.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, Integer.MAX_VALUE, 100, true)); - } - else { - creature.removePotionEffect(PotionEffectType.SLOW); - } - } - - /** - * Registers the listener if it wasn't registered, and unregisters this listener - * if there isn't any frozen player. - * - * Call this AFTER registering the first frozen player, and AFTER unregistering - * the last one. - */ - private void updateListenerRegistration() { - // Registers the listener if needed - // (i.e if there isn't any frozen player, or if the global freeze is enabled). - if(!this.isListenerRegistered) { - if(!this.frozenPlayers.isEmpty() || this.getGlobalFreezeState()) { - p.getServer().getPluginManager().registerEvents(freezerListener, p); - this.isListenerRegistered = true; - } - } - - // Unregisters the listener if needed - else { - if(this.frozenPlayers.isEmpty() && !this.getGlobalFreezeState()) { - HandlerList.unregisterAll(freezerListener); - this.isListenerRegistered = false; - } - } - } - - - /** - * Returns the list of the currently frozen players. - * - * @return The list. - */ - public ArrayList<Player> getFrozenPlayers() { - - ArrayList<Player> frozenPlayersList = new ArrayList<Player>(); - - for(UUID id : frozenPlayers) { - frozenPlayersList.add(p.getServer().getPlayer(id)); - } - - return frozenPlayersList; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/misc/MOTDManager.java b/src/main/java/me/azenet/UHPlugin/misc/MOTDManager.java deleted file mode 100644 index 4fedeaa..0000000 --- a/src/main/java/me/azenet/UHPlugin/misc/MOTDManager.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.misc; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.teams.UHTeam; -import org.bukkit.ChatColor; - -public class MOTDManager { - - private UHPlugin p; - private I18n i; - - private boolean enabled; - private String matchName = ""; - - private String currentMOTD; - - public MOTDManager(UHPlugin plugin) { - p = plugin; - i = p.getI18n(); - - enabled = p.getConfig().getBoolean("motd.enabled"); - - if(enabled && p.getConfig().getBoolean("motd.displayMatchName")) { - matchName = ChatColor.translateAlternateColorCodes('&', p.getConfig().getString("motd.matchNamePrefix")) + p.getScoreboardManager().getScoreboardName() + ChatColor.RESET + "\n"; - } - } - - /** - * Returns the current MOTD. - * - * @return The MOTD. - */ - public String getCurrentMOTD() { - return currentMOTD; - } - - /** - * Returns true if the state-based MOTDs are enabled. - * - * @return true if enabled. - */ - public boolean isEnabled() { - return enabled; - } - - - /** - * Updates the MOTD to the one displayed before the game start. - */ - public void updateMOTDBeforeStart() { - if(enabled) currentMOTD = matchName + i.t("motd.beforeStart"); - } - - /** - * Updates the MOTD to the one displayed during the start. - */ - public void updateMOTDDuringStart() { - if(enabled) currentMOTD = matchName + i.t("motd.starting"); - } - - /** - * Updates the MOTD to the one displayed during the game (includes alive counts). - * <p> - * This need to be called on each death, to update alive counts. - */ - public void updateMOTDDuringGame() { - if(enabled) { - if(!p.getGameManager().isGameWithTeams()) { - currentMOTD = matchName + i.t("motd.runningSolo", String.valueOf(p.getGameManager().getAlivePlayersCount())); - } - else { - currentMOTD = matchName + i.t("motd.runningTeams", String.valueOf(p.getGameManager().getAlivePlayersCount()), String.valueOf(p.getGameManager().getAliveTeamsCount())); - } - } - } - - /** - * Updates the MOTD after the game. - * - * @param winner The winner. - */ - public void updateMOTDAfterGame(UHTeam winner) { - if(enabled) { - if(!p.getGameManager().isGameWithTeams()) { - currentMOTD = matchName + i.t("motd.finishedSolo", winner.getName()); - } - else { - currentMOTD = matchName + i.t("motd.finishedTeams", winner.getDisplayName()); - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/misc/ProTipsSender.java b/src/main/java/me/azenet/UHPlugin/misc/ProTipsSender.java deleted file mode 100644 index 3e2fc1e..0000000 --- a/src/main/java/me/azenet/UHPlugin/misc/ProTipsSender.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.misc; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.utils.UHSound; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - - -/** - * Sends a ProTip to a player. - * - * All ProTips are sent only once. - * - * The name of a protip (the value of the static attribute representing it) is: - * - an identifier; - * - the name of the key in the translation files (protips.{name}); - * - the name of the key to disable it in the config file (protips.{name} too). - * - * @author Amaury Carrade - * - */ -public class ProTipsSender { - - UHPlugin p = null; - I18n i = null; - - Map<String,ArrayList<UUID>> protipsGiven = new HashMap<String,ArrayList<UUID>>(); - - UHSound proTipsSound = null; - - public static final String PROTIP_LOCK_CHAT = "teamchat.lock"; - public static final String PROTIP_USE_G_COMMAND = "teamchat.useGCommand"; - public static final String PROTIP_USE_T_COMMAND = "teamchat.useTCommand"; - - public static final String PROTIP_CRAFT_GOLDEN_HEAD = "crafts.goldenHead"; - public static final String PROTIP_CRAFT_COMPASS_EASY = "crafts.compassEasy"; - public static final String PROTIP_CRAFT_COMPASS_MEDIUM = "crafts.compassMedium"; - public static final String PROTIP_CRAFT_COMPASS_HARD = "crafts.compassHard"; - public static final String PROTIP_CRAFT_GLISTERING_MELON = "crafts.glisteringMelon"; - public static final String PROTIP_CRAFT_NO_ENCHANTED_GOLDEN_APPLE = "crafts.noEnchGoldenApple"; - - public static final String PROTIP_STARTUP_INVINCIBILITY = "start.invincibility"; - - public ProTipsSender(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - - // Initialization of the "protips" map - protipsGiven.put(PROTIP_LOCK_CHAT, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_USE_G_COMMAND, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_USE_T_COMMAND, new ArrayList<UUID>()); - - protipsGiven.put(PROTIP_CRAFT_GOLDEN_HEAD, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_CRAFT_COMPASS_EASY, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_CRAFT_COMPASS_MEDIUM, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_CRAFT_COMPASS_HARD, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_CRAFT_GLISTERING_MELON, new ArrayList<UUID>()); - protipsGiven.put(PROTIP_CRAFT_NO_ENCHANTED_GOLDEN_APPLE, new ArrayList<UUID>()); - - protipsGiven.put(PROTIP_STARTUP_INVINCIBILITY, new ArrayList<UUID>()); - - - // Sound - proTipsSound = new UHSound(p.getConfig().getConfigurationSection("protips.sound")); - } - - - /** - * Sends a ProTip to a player. - * A ProTip is only given one time to a given player. - * - * @param player The player - * @param protip The ProTip to send to this player. - * @return true if the ProTip was sent, false else (already sent or disabled by the config). - * - * @throws IllegalArgumentException if the ProTip is not registered. - */ - public boolean sendProtip(Player player, String protip) { - - if(!protipsGiven.containsKey(protip)) { - throw new IllegalArgumentException("Unknown ProTip"); - } - - if(!isProtipEnabled(protip)) { - return false; - } - - if(wasProtipSent(player, protip)) { - return false; - } - - protipsGiven.get(protip).add(player.getUniqueId()); - - - player.sendMessage(i.t("protips.base") + " " + ChatColor.RESET + i.t("protips." + protip)); - proTipsSound.play(player); - - return false; - } - - /** - * Checks if a ProTip was already sent to a player. - * - * @param player The player. - * @param protip The ProTip. - * @return true if the ProTip was sent; false else. - * - * @throws IllegalArgumentException if the ProTip is not registered. - */ - public boolean wasProtipSent(Player player, String protip) { - if(!protipsGiven.containsKey(protip)) { - throw new IllegalArgumentException("Unknown ProTip"); - } - - return protipsGiven.get(protip).contains(player.getUniqueId()); - } - - /** - * Checks if the given ProTip is enabled in the config. - * - * @param protip The ProTip to check. - * - * @return true if the ProTip is enabled. - */ - public boolean isProtipEnabled(String protip) { - return p.getConfig().getBoolean("protips." + protip); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/misc/RuntimeCommandsExecutor.java b/src/main/java/me/azenet/UHPlugin/misc/RuntimeCommandsExecutor.java deleted file mode 100644 index 9c72eee..0000000 --- a/src/main/java/me/azenet/UHPlugin/misc/RuntimeCommandsExecutor.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.misc; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.task.ScheduledCommandsExecutorTask; -import me.azenet.UHPlugin.utils.UHUtils; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - - -/** - * This will execute the commands to be executed during runtime, as configured in the config.yml file - * or added through the API. - */ -public class RuntimeCommandsExecutor { - - private UHPlugin p = null; - - /** - * Stores the commands to be executed later. - * <p> - * The first map (String->HashMap) associates a key to a group of commands launched at the same time.<br> - * The sub-map (Integer->HashSet) associates a delay, in seconds, with a set containing the commands to be - * executed this number of seconds after the call of the {@link #registerCommandsInScheduler(String)} - * method. - */ - private Map<String, HashMap<Integer, HashSet<String>>> scheduled = new HashMap<String, HashMap<Integer, HashSet<String>>>(); - - - /** - * The key for the commands executed when the server starts. - */ - public final static String AFTER_SERVER_START = "internal.server-start"; - - /** - * The key for the commands executed after the beginning of the game. - */ - public final static String AFTER_GAME_START = "internal.game-start"; - - /** - * The key for the commands executed after the end of the game. - */ - public final static String AFTER_GAME_END = "internal.game-end"; - - - public RuntimeCommandsExecutor(UHPlugin plugin) { - p = plugin; - - importFromConfig("commands.execute-server-start", AFTER_SERVER_START); - importFromConfig("commands.execute-start", AFTER_GAME_START); - importFromConfig("commands.execute-end", AFTER_GAME_END); - } - - /** - * Register the commands registered under the given key in the Bukkit' scheduler. - * <p> - * Delays are from the execution of this method. - * - * @param key The key to schedule. All commands previously registered under this key will be executed. - */ - public void registerCommandsInScheduler(String key) { - registerCommandsInScheduler(scheduled.get(key)); - } - - /** - * Register the given commands in the Bukkit' scheduler. - * - * Delays are from the execution of this method. - * @param scheduledCommands - */ - private void registerCommandsInScheduler(Map<Integer, HashSet<String>> scheduledCommands) { - if(scheduledCommands != null) { - for(Entry<Integer, HashSet<String>> scheduledCommandsStack : scheduledCommands.entrySet()) { - p.getServer().getScheduler().runTaskLater( - p, - new ScheduledCommandsExecutorTask(p, scheduledCommandsStack.getValue()), - scheduledCommandsStack.getKey() * 20l - ); - } - } - } - - - - /** - * Schedules a command. - * <p> - * To schedule a command executed by the plugin, like in the configuration file, you will have - * to use the keys defined as static attributes of this class: - * {@link #AFTER_SERVER_START}, {@link #AFTER_GAME_END} and {@link #AFTER_GAME_START}. - * - * @param key The command will be stored under this key. - * The keys internally used by the plugin start by "{@code internal.}". - * @param command The command to add. - * @param delay The delay (seconds). - */ - public void scheduleCommand(String key, String command, Integer delay) { - if(!scheduled.containsKey(key)) { - scheduled.put(key, new HashMap<Integer, HashSet<String>>()); - } - - scheduleCommand(scheduled.get(key), command, delay); - } - - /** - * Schedules a command. - * - * @param commands A map containing the scheduled commands, sorted by delay. - * @param command The command to add. - * @param delay The delay (seconds). - */ - private void scheduleCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) { - HashSet<String> list = scheduledCommands.get(delay); - - if(list == null) { - list = new HashSet<String>(); - scheduledCommands.put(delay, list); - } - - list.add(clearCommandName(command)); - } - - - /** - * Removes the given command from everywhere. - * - * @param key The command will be stored under this key. - * The keys internally used by the plugin start by "{@code internal.}". - * @param command The command. Not case-sensitive. - */ - public void removeScheduledCommand(String key, String command) { - removeScheduledCommand(scheduled.get(key), command); - } - - /** - * Removes the given command from everywhere. - * - * @param scheduledCommands A map containing the scheduled commands, sorted by delay. - * @param command The command. Not case-sensitive. - */ - private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command) { - for(HashSet<String> commands : scheduledCommands.values()) { - for(String scheduledCommand : new HashSet<String>(commands)) { - if(scheduledCommand.equalsIgnoreCase(clearCommandName(command))) { - commands.remove(scheduledCommand); - } - } - } - } - - - /** - * Removes the given command from everywhere. - * - * @param key The command will be stored under this key. - * The keys internally used by the plugin start by "{@code internal.}". - * @param command The command. Not case-sensitive. - */ - public void removeScheduledCommand(String key, String command, Integer delay) { - removeScheduledCommand(scheduled.get(key), command, delay); - } - - /** - * Removes the given command from everywhere. - * - * @param scheduledCommands A map containing the scheduled commands, sorted by delay. - * @param command The command. Not case-sensitive. - */ - private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) { - HashSet<String> commands = scheduledCommands.get(delay); - - if(commands != null) { - for(String scheduledCommand : commands) { - if(scheduledCommand.equalsIgnoreCase(clearCommandName(command))) { - commands.remove(scheduledCommand); - } - } - } - } - - - /* Utilities */ - - /** - * Imports the commands stored in the configuration. - * - * @param path The path in the config file. - * @param scheduledCommands A map containing the scheduled commands, sorted by delay. - */ - private void importFromConfig(String path, String key) { - List<Map<?, ?>> rawCommands = p.getConfig().getMapList(path); - - if(rawCommands != null) { - for(Map<?, ?> rawCommand : rawCommands) { - String cmd = String.valueOf(rawCommand.get("exec")); - Integer delay; - - if(cmd == null || cmd.isEmpty()) continue; - - try { - delay = UHUtils.string2Time(String.valueOf(rawCommand.get("delay"))); - } catch(IllegalArgumentException e) { - delay = 0; - } - - scheduleCommand(key, cmd, delay); - } - } - } - - - - private String clearCommandName(String command) { - if(command.startsWith("/")) { - command = command.substring(1); - } - - return command; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/recipes/RecipesManager.java b/src/main/java/me/azenet/UHPlugin/recipes/RecipesManager.java deleted file mode 100644 index b9a8b83..0000000 --- a/src/main/java/me/azenet/UHPlugin/recipes/RecipesManager.java +++ /dev/null @@ -1,475 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.recipes; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.SkullType; -import org.bukkit.inventory.*; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.SkullMeta; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - - -public class RecipesManager { - - private UHPlugin p = null; - private I18n i = null; - - private Material compassCentralIngredient = null; - private int compassRecipeType = -1; - - public static final String RECIPE_COMPASS = "compass"; - public static final String RECIPE_GLISTERING_MELON = "glistering"; - public static final String RECIPE_ENCHANTED_GOLDEN_APPLE = "EGA"; - - public static final int COMPASS_DISABLED = 0; - public static final int COMPASS_EASY = 1; - public static final int COMPASS_MEDIUM = 2; - public static final int COMPASS_HARD = 3; - - private String lastFailedRecipe = null; - - - public RecipesManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - } - - - /** - * Registers the recipes needed, following the configuration. - */ - public void registerRecipes() { - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.do")) { - p.getServer().addRecipe(getGoldenHeadHumanRecipe()); - } - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.do")) { - p.getServer().addRecipe(getGoldenHeadMonsterRecipe()); - } - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.addLore") || p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.addLore")) { - p.getServer().addRecipe(getLoreRemoverNormalRecipe()); - p.getServer().addRecipe(getLoreRemoverNotchRecipe()); - } - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenMelonWithGoldBlock")) { - p.getServer().addRecipe(getGoldenMelonRecipe()); - } - - // Because the compass recipe is "semi-shapeless" (the central part is fixed, but the - // loots can be placed into any configuration), there isn't a registered recipe for it - // (I don't want to register 16 recipes for each difficulty). - // Instead, using the inventoryClickEvent/inventoryDragEvent, we checks manually if the - // recipe is valid. - switch(this.getCompassRecipeType()) { - case COMPASS_EASY: - compassCentralIngredient = Material.REDSTONE; - break; - case COMPASS_MEDIUM: - compassCentralIngredient = Material.ENDER_PEARL; - break; - case COMPASS_HARD: - compassCentralIngredient = Material.EYE_OF_ENDER; - break; - case COMPASS_DISABLED: - break; - } - } - - /** - * Checks if a recipe is allowed. - * - * @param recipe - * @return True if the recipe is allowed, false else. - */ - public boolean isRecipeAllowed(Recipe recipe) { - - // Vanilla compass recipe is disabled if the special compass is used. - if(p.getConfig().getBoolean("gameplay-changes.compass.enabled") && RecipeUtil.areSimilar(recipe, getVanillaCompassRecipe())) { - this.lastFailedRecipe = RECIPE_COMPASS; - return false; - } - - // Vanilla golden melon recipe is disabled if the craft with a gold block is enabled. - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenMelonWithGoldBlock") && RecipeUtil.areSimilar(recipe, getVanillaGoldenMelonRecipe())) { - this.lastFailedRecipe = RECIPE_GLISTERING_MELON; - return false; - } - - // If enchanted golden apples are disabled... - // The same technique does not work, this is a workaround - if(p.getConfig().getBoolean("gameplay-changes.goldenApple.disableNotchApples")) { - if(recipe.getResult().getType() == Material.GOLDEN_APPLE) { - for(ItemStack item : RecipeUtil.getListOfIngredients(recipe)) { - if(item.getType() == Material.GOLD_BLOCK) { - // There is a gold block in a recipe for a golden apple - NOPE NOPE NOPE - this.lastFailedRecipe = RECIPE_ENCHANTED_GOLDEN_APPLE; - return false; - } - } - } - } - - // The recipe is allowed. - return true; - } - - /** - * Checks if the recipe is a valid compass recipe. - * <p> - * A valid compass recipe is a recipe with: - * <ul> - * <li> - * in the center, the valid ingredient for the current compass craft - * (redstone, ender pearl or eye of ender); - * </li> - * <li> - * four iron ingots placed like the vanilla compass recipe; - * </li> - * <li> - * in the four corners, a bone, a rotten flesh, a spider eye and a gunpowder, - * placed in any shape. - * </li> - * </ul> - * <p> - * Executed in the {@code onInventoryClick} and {@code onInventoryDrag} events, to allow this to be recognized even if - * the recipe is not registered. - * - * @param matrix The content of the crafting inventory. - * @return true if the recipe is an alternate recipe for the compass. - */ - public boolean isValidCompassRecipe(ItemStack[] matrix) { - if(matrix.length <= 5) { - return false; // Small crafting grid - } - - if(this.getCompassRecipeType() == COMPASS_DISABLED) { - return false; - } - - - // 1: check of the static part (central ingredient + iron) - - Material iron1 = matrix[1].getType(); - Material iron2 = matrix[3].getType(); - Material iron3 = matrix[5].getType(); - Material iron4 = matrix[7].getType(); - Material centralIngredient = matrix[4].getType(); - - if(!(iron1.equals(Material.IRON_INGOT) - && iron2.equals(Material.IRON_INGOT) - && iron3.equals(Material.IRON_INGOT) - && iron4.equals(Material.IRON_INGOT) - && centralIngredient.equals(compassCentralIngredient))) { - return false; - } - - // 2: check of the dynamic part (loots) - - ArrayList<Material> corners = new ArrayList<Material>(); - corners.add(matrix[0].getType()); - corners.add(matrix[2].getType()); - corners.add(matrix[6].getType()); - corners.add(matrix[8].getType()); - - if(!(corners.contains(Material.BONE) - && corners.contains(Material.ROTTEN_FLESH) - && corners.contains(Material.SPIDER_EYE) - && corners.contains(Material.SULPHUR))) { - return false; - } - - return true; - } - - - /** - * Adds the lore to the golden apples, if needed. - * - * @param recipe The recipe to change. - * @param inventory The crafting inventory (used to access the skull owner) - * @return The modified result (ItemStack) if a change was needed. Null if no change is needed. - */ - public ItemStack addLore(Recipe recipe, CraftingInventory inventory) { - if((p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.do") || p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.do")) - && (p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.addLore") || p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.addLore")) - && (RecipeUtil.areSimilar(recipe, getGoldenHeadHumanRecipe()) || RecipeUtil.areSimilar(recipe, getGoldenHeadMonsterRecipe()))) { - - ItemStack result = recipe.getResult(); - ItemMeta meta = result.getItemMeta(); - - // Lookup for the head in the recipe - String name = ""; - Boolean wither = true; - - for(ItemStack item : inventory.getContents()) { - if(item.getType() == Material.SKULL_ITEM && item.getDurability() == (short) SkullType.PLAYER.ordinal()) { // An human head - SkullMeta sm = (SkullMeta) item.getItemMeta(); - if(sm.hasOwner()) { // An human head - name = sm.getOwner(); - wither = false; - } - break; - } - } - - if((wither && p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.addLore")) - || (!wither && p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.addLore"))) { - - List<String> lore = null; - if(wither) { - lore = Arrays.asList(i.t("craft.goldenApple.loreLine1Monster"), i.t("craft.goldenApple.loreLine2Monster")); - } - else { - lore = Arrays.asList(i.t("craft.goldenApple.loreLine1Player", name), i.t("craft.goldenApple.loreLine2Player", name)); - } - meta.setLore(lore); - - } - - result.setItemMeta(meta); - return result; - } - - return null; - } - - /** - * Changes the name of the result item of the anti-lore recipe, - * to keep the same name than the original. - * - * @param recipe The recipe. - * @param inventory The crafting inventory. Used to get the name of the item placed in the inventory grid. - * @return The ItemStack if a change was needed; null else. - */ - public ItemStack keepNameOnLoreRemover(Recipe recipe, CraftingInventory inventory) { - if((p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.addLore") || p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.addLore")) - && (RecipeUtil.areSimilar(recipe, getLoreRemoverNormalRecipe()) || RecipeUtil.areSimilar(recipe, getLoreRemoverNotchRecipe()))) { - - ItemStack original = null; - for(int slot = 0; slot <= 9; slot++) { - original = inventory.getMatrix()[slot]; - if(original.getType() != Material.AIR) { - break; // Found (because there is only one item in the craft). - } - } - - ItemMeta metaOriginal = original.getItemMeta(); - - if(metaOriginal != null && metaOriginal.hasDisplayName()) { - ItemStack result = recipe.getResult(); - ItemMeta metaResult = result.getItemMeta(); - - metaResult.setDisplayName(metaOriginal.getDisplayName()); - result.setItemMeta(metaResult); - - return result; - } - - return null; - } - - return null; - } - - - - /** - * Returns the current compass recipe. - * - * @return {@link RecipesManager#COMPASS_DISABLED}, {@link RecipesManager#COMPASS_EASY}, - * {@link RecipesManager#COMPASS_MEDIUM} or {@link RecipesManager#COMPASS_HARD}. - */ - public int getCompassRecipeType() { - if(compassRecipeType != -1) { - return compassRecipeType; - } - - if (p.getConfig().getBoolean("gameplay-changes.compass.enabled")) { - switch(p.getConfig().getString("gameplay-changes.compass.recipe").toLowerCase()) { - case "easy": - compassRecipeType = COMPASS_EASY; - break; - - case "hard": - compassRecipeType = COMPASS_HARD; - break; - - default: - compassRecipeType = COMPASS_MEDIUM; - break; - } - } - else { - compassRecipeType = COMPASS_DISABLED; - } - - return compassRecipeType; - } - - /** - * Returns the recipe that transforms 8 gold ingots and 1 human head into - * a golden apple. - * - * @return The shaped recipe. - */ - public ShapedRecipe getGoldenHeadHumanRecipe() { - short damage = 0; - String name = i.t("craft.goldenApple.nameGoldenAppleFromHeadNormal"); - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromHuman.craftNotchApple")) { - damage = 1; - name = i.t("craft.goldenApple.nameGoldenAppleFromHeadNotch"); - } - - ItemStack goldenAppleStack = new ItemStack(Material.GOLDEN_APPLE, p.getConfig().getInt("gameplay-changes.craftGoldenAppleFromHead.fromHuman.numberCrafted", 1), damage); - ItemMeta goldenAppleMeta = goldenAppleStack.getItemMeta(); - goldenAppleMeta.setDisplayName(ChatColor.RESET + name); - goldenAppleStack.setItemMeta(goldenAppleMeta); - - ShapedRecipe goldenAppleFromHeadRecipe = new ShapedRecipe(goldenAppleStack); - - goldenAppleFromHeadRecipe.shape("GGG", "GHG", "GGG"); - goldenAppleFromHeadRecipe.setIngredient('G', Material.GOLD_INGOT); - goldenAppleFromHeadRecipe.setIngredient('H', Material.SKULL_ITEM, SkullType.PLAYER.ordinal()); // TODO: deprecated, but no alternative found... - - return goldenAppleFromHeadRecipe; - } - - /** - * Returns the recipe that transforms 8 gold ingots and 1 wither head into - * a golden apple. - * - * @return The shaped recipe. - */ - public ShapedRecipe getGoldenHeadMonsterRecipe() { - short damage = 0; - String name = i.t("craft.goldenApple.nameGoldenAppleFromHeadNormal"); - - if(p.getConfig().getBoolean("gameplay-changes.craftGoldenAppleFromHead.fromWither.craftNotchApple")) { - damage = 1; - name = i.t("craft.goldenApple.nameGoldenAppleFromHeadNotch"); - } - - ItemStack goldenAppleStack = new ItemStack(Material.GOLDEN_APPLE, p.getConfig().getInt("gameplay-changes.craftGoldenAppleFromHead.fromWither.numberCrafted", 1), damage); - ItemMeta goldenAppleMeta = goldenAppleStack.getItemMeta(); - goldenAppleMeta.setDisplayName(ChatColor.RESET + name); - goldenAppleStack.setItemMeta(goldenAppleMeta); - - ShapedRecipe goldenAppleFromWitherHeadRecipe = new ShapedRecipe(goldenAppleStack); - - goldenAppleFromWitherHeadRecipe.shape("GGG", "GHG", "GGG"); - goldenAppleFromWitherHeadRecipe.setIngredient('G', Material.GOLD_INGOT); - goldenAppleFromWitherHeadRecipe.setIngredient('H', Material.SKULL_ITEM, SkullType.WITHER.ordinal()); // TODO: deprecated, but no alternative found... - - return goldenAppleFromWitherHeadRecipe; - } - - /** - * Returns the recipe that transforms one golden apple into one golden apple. - * Used to remove the lore, so two apples from a different head are stackable. - * - * @return The shapeless recipe. - */ - public ShapelessRecipe getLoreRemoverNormalRecipe() { - ShapelessRecipe goldenAppleLoreRemoverRecipe = new ShapelessRecipe(new ItemStack(Material.GOLDEN_APPLE, 1, (short) 0)); - goldenAppleLoreRemoverRecipe.addIngredient(Material.GOLDEN_APPLE); - - return goldenAppleLoreRemoverRecipe; - } - - /** - * Returns the recipe that transforms one enchanted golden apple into one enchanted - * golden apple. - * Used to remove the lore, so two apples from a different head are stackable. - * - * @return The shapeless recipe. - */ - public ShapelessRecipe getLoreRemoverNotchRecipe() { - ShapelessRecipe goldenAppleLoreRemoverNotchRecipe = new ShapelessRecipe(new ItemStack(Material.GOLDEN_APPLE, 1, (short) 1)); - goldenAppleLoreRemoverNotchRecipe.addIngredient(Material.GOLDEN_APPLE, 1); - - return goldenAppleLoreRemoverNotchRecipe; - } - - /** - * Returns the recipe that transforms one melon and one gold block into a golden melon. - * - * @return The shapeless recipe. - */ - public ShapelessRecipe getGoldenMelonRecipe() { - ShapelessRecipe goldenMelonRecipe = new ShapelessRecipe(new ItemStack(Material.SPECKLED_MELON)); - goldenMelonRecipe.addIngredient(1, Material.GOLD_BLOCK); - goldenMelonRecipe.addIngredient(1, Material.MELON); - - return goldenMelonRecipe; - } - - /** - * Returns the vanilla recipe for the compass. - * - * @return The shaped recipe. - */ - public ShapedRecipe getVanillaCompassRecipe() { - ShapedRecipe vanillaCompassRecipe = new ShapedRecipe(new ItemStack(Material.COMPASS)); - vanillaCompassRecipe.shape(" I ", "IRI", " I "); - - vanillaCompassRecipe.setIngredient('I', Material.IRON_INGOT); - vanillaCompassRecipe.setIngredient('R', Material.REDSTONE); - - return vanillaCompassRecipe; - } - - /** - * Returns the vanilla recipe for the golden melon. - * - * @return The shaped recipe. - */ - public ShapedRecipe getVanillaGoldenMelonRecipe() { - ShapedRecipe vanillaGoldenMelonRecipe = new ShapedRecipe(new ItemStack(Material.SPECKLED_MELON)); - vanillaGoldenMelonRecipe.shape("GGG", "GMG", "GGG"); - - vanillaGoldenMelonRecipe.setIngredient('G', Material.GOLD_NUGGET); - vanillaGoldenMelonRecipe.setIngredient('M', Material.MELON); - - return vanillaGoldenMelonRecipe; - } - - - /** - * Returns the last failed recipe. - * - * Use {@link RecipesManager#RECIPE_COMPASS}, {@link RecipesManager#RECIPE_GLISTERING_MELON} and - * {@link RecipesManager#RECIPE_ENCHANTED_GOLDEN_APPLE} to get the type of the failed recipe. - * - * @return the lastFailedRecipe - */ - public String getLastFailedRecipe() { - return lastFailedRecipe; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/scoreboard/ScoreboardManager.java b/src/main/java/me/azenet/UHPlugin/scoreboard/ScoreboardManager.java deleted file mode 100644 index 125bc20..0000000 --- a/src/main/java/me/azenet/UHPlugin/scoreboard/ScoreboardManager.java +++ /dev/null @@ -1,443 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.scoreboard; - -import me.azenet.UHPlugin.UHGameManager; -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.timers.UHTimer; - -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scoreboard.Criterias; -import org.bukkit.scoreboard.DisplaySlot; -import org.bukkit.scoreboard.Objective; -import org.bukkit.scoreboard.Scoreboard; - -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; - -public class ScoreboardManager { - - private UHPlugin p = null; - private I18n i = null; - private UHGameManager gm = null; - private Scoreboard sb = null; - private SidebarObjective sidebar = null; - - // Old values, to be able to update the minimum. - // Initialized to -1 to force an update at the first launch. - private Integer oldEpisode = -1; - private Integer oldAlivePlayersCount = -1; - private Integer oldAliveTeamsCount = -1; - - // Timers - private List<UHTimer> displayedTimers = new ArrayList<UHTimer>(); - - - // Static values - private String objectiveName = "UHPlugin"; - private NumberFormat formatter = new DecimalFormat("00"); - - - /** - * Constructor. - * Initializes the scoreboard. - * - * @param plugin - */ - public ScoreboardManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - this.gm = p.getGameManager(); - this.sb = Bukkit.getServer().getScoreboardManager().getNewScoreboard(); - - - // Initialization of the scoreboard (match info in the sidebar) - if(p.getConfig().getBoolean("scoreboard.enabled")) { - try { - sb.clearSlot(DisplaySlot.SIDEBAR); - sb.getObjective(objectiveName).unregister(); - } catch(NullPointerException | IllegalArgumentException ignored) { } - - sidebar = new SidebarObjective(sb, objectiveName); - sidebar.setDisplayName(getScoreboardName()); - - buildSidebar(); - } - - // Initialization of the scoreboard (health in players' list) - if(p.getConfig().getBoolean("scoreboard.health")) { - Objective healthObjective = sb.registerNewObjective("Health", Criterias.HEALTH); - healthObjective.setDisplayName("Health"); - healthObjective.setDisplaySlot(DisplaySlot.PLAYER_LIST); - - // Sometimes, the health is initialized to 0. This is used to fix this. - updateHealthScore(); - } - else { - sb.clearSlot(DisplaySlot.PLAYER_LIST); // Just in case - } - } - - /** - * Used to displays the player count before the beginning of the game. - * - * To be called when a player joins. - */ - public void addPlayerBeforeStart() { - sidebar.updateEntry(this.getText("players", p.getServer().getOnlinePlayers().size() - 1), - this.getText("players", p.getServer().getOnlinePlayers().size())); - } - - /** - * Used to displays the player count before the beginning of the game. - * - * To be called when a player leaves. - */ - public void removePlayerBeforeStart() { - sidebar.updateEntry(this.getText("players", p.getServer().getOnlinePlayers().size() + 1), - this.getText("players", p.getServer().getOnlinePlayers().size())); - } - - /** - * Re-builds the sidebar from scratch. - */ - public void buildSidebar() { - if(!p.getConfig().getBoolean("scoreboard.enabled")) { - return; - } - - sidebar.reset(true); - - // Initial state (before start) - if(!gm.isGameStarted()) { - if(p.getConfig().getBoolean("episodes.enabled")) { - sidebar.addEntry(this.getText("episode", 0), true); - } - - sidebar.addEntry(this.getText("players", p.getServer().getOnlinePlayers().size()), true); - - if(p.getConfig().getBoolean("episodes.enabled") && p.getConfig().getBoolean("scoreboard.timer")) { - sidebar.addEntry(SidebarObjective.SEPARATOR, true); - - // Displays a fake, frozen timer if the game is not started. - sidebar.addEntry(this.getTimerText(new UHTimer(""), true, false), true); - } - - buildTimersSidebar(); - displayFreezeState(); - - sidebar.reconstruct(); - } - - // In-game state - else { - if(p.getConfig().getBoolean("episodes.enabled") && p.getConfig().getBoolean("scoreboard.episode")) { - sidebar.addEntry(this.getText("episode", gm.getEpisode()), true); - oldEpisode = gm.getEpisode(); - } - - if(p.getConfig().getBoolean("scoreboard.players")) { - sidebar.addEntry(this.getText("players", p.getGameManager().getAlivePlayersCount()), true); - oldAlivePlayersCount = p.getGameManager().getAlivePlayersCount(); - } - - if(gm.isGameWithTeams() && p.getConfig().getBoolean("scoreboard.teams")) { - sidebar.addEntry(this.getText("teams", p.getGameManager().getAliveTeamsCount()), true); - oldAliveTeamsCount = p.getGameManager().getAliveTeamsCount(); - } - - if(p.getConfig().getBoolean("episodes.enabled") && p.getConfig().getBoolean("scoreboard.timer") && p.getTimerManager().getMainTimer() != null) { - sidebar.addEntry(SidebarObjective.SEPARATOR, true); - sidebar.addEntry(getTimerText(p.getTimerManager().getMainTimer(), false, false), true); - } - - buildTimersSidebar(); - displayFreezeState(); - - sidebar.reconstruct(); - } - } - - /** - * Adds the timers to the sidebar. - * - * <p>Appends to the current sidebar. This method will *not* reconstruct the sidebar.</p> - */ - private void buildTimersSidebar() { - for(UHTimer timer : displayedTimers) { - sidebar.addEntry(SidebarObjective.SEPARATOR, true); - sidebar.addEntry(timer.getDisplayName(), true); - sidebar.addEntry(getTimerText(timer, false, false), true); - } - } - - /** - * Displays a timer in the scoreboard. - * - * @param timer - */ - public void displayTimer(UHTimer timer) { - if(!displayedTimers.contains(timer)) { - displayedTimers.add(timer); - buildSidebar(); - } - } - - /** - * Hides a timer, in the scoreboard. - * - * @param timer - */ - public void hideTimer(UHTimer timer) { - if(displayedTimers.remove(timer)) { - buildSidebar(); - } - } - - /** - * The sidebar needs to be reconstructed when the timers are restarted, to avoid - * duplicated values. - */ - public void restartTimers() { - if(p.getConfig().getBoolean("scoreboard.enabled")) { - buildSidebar(); - } - } - - /** - * Updates the timers of the scoreboard (if needed). - */ - public void updateTimers() { - if(p.getConfig().getBoolean("scoreboard.enabled") && !p.getFreezer().getGlobalFreezeState()) { - - // Main timer - if(p.getConfig().getBoolean("episodes.enabled") && p.getConfig().getBoolean("scoreboard.timer") && p.getTimerManager().getMainTimer() != null) { - sidebar.updateEntry(getTimerText(p.getTimerManager().getMainTimer(), false, true), getTimerText(p.getTimerManager().getMainTimer(), false, false)); - } - - - // Other timers - for(UHTimer timer : displayedTimers) { - sidebar.updateEntry(getTimerText(timer, false, true), getTimerText(timer, false, false)); - } - - } - } - - /** - * Updates the counters of the scoreboard (if needed). - */ - public void updateCounters() { - if(p.getConfig().getBoolean("scoreboard.enabled")) { - Integer episode = gm.getEpisode(); - Integer alivePlayersCount = gm.getAlivePlayersCount(); - Integer aliveTeamsCount = gm.getAliveTeamsCount(); - - if(!episode.equals(oldEpisode) && p.getConfig().getBoolean("episodes.enabled") && p.getConfig().getBoolean("scoreboard.episode")) { - if(oldEpisode == -1) oldEpisode = 0; // May happens the first time - - sidebar.updateEntry(getText("episode", oldEpisode), getText("episode", episode)); - oldEpisode = episode; - } - - if(!alivePlayersCount.equals(oldAlivePlayersCount) && p.getConfig().getBoolean("scoreboard.players")) { - // Needed if the game is launched without any player, and players are marked as alive later. - if(oldAlivePlayersCount == -1) oldAlivePlayersCount = 0; - - sidebar.updateEntry(getText("players", oldAlivePlayersCount), getText("players", alivePlayersCount)); - oldAlivePlayersCount = alivePlayersCount; - } - - if(gm.isGameWithTeams() && !aliveTeamsCount.equals(oldAliveTeamsCount) && p.getConfig().getBoolean("scoreboard.teams")) { - // Needed if the game is launched without any player, and players are marked as alive later. - if(oldAliveTeamsCount == -1) oldAliveTeamsCount = 0; - - sidebar.updateEntry(getText("teams", oldAliveTeamsCount), getText("teams", aliveTeamsCount)); - oldAliveTeamsCount = aliveTeamsCount; - } - } - } - - /** - * Displays the given freeze state in the scoreboard. - * - * @param frozen If {@code true}, the "frozen" text will be displayed. Else, hidden. - */ - private void displayFreezeState(boolean frozen) { - if(p.getConfig().getBoolean("scoreboard.enabled", true) && p.getConfig().getBoolean("scoreboard.freezeStatus", true)) { - - final String freezerStatusText = i.t("freeze.scoreboard"); - - if(frozen) { - sidebar.addEntry(SidebarObjective.SEPARATOR, true); - sidebar.addEntry(freezerStatusText, true); - sidebar.reconstruct(); - } - else { - int sepIndex = sidebar.getEntryIndex(freezerStatusText) - 1; - if(sepIndex != -2) { - sidebar.removeEntryAtIndex(sepIndex, true); - sidebar.removeEntry(freezerStatusText, true); - sidebar.reconstruct(); - } - } - } - } - - /** - * Displays the freeze state in the scoreboard. - */ - public void displayFreezeState() { - displayFreezeState(p.getFreezer().getGlobalFreezeState()); - } - - /** - * Returns the text displayed in the scoreboard. - * - * @param textType Either "episode", "players" or "teams". - * @param arg Respectively, the episode number, the players count and the teams count. - * @return The text. - * @throws IllegalArgumentException if the textType is not one of the listed types. - */ - private String getText(String textType, Integer arg) { - switch(textType) { - case "episode": - return i.t("scoreboard.episode", arg.toString()); - case "players": - return i.t("scoreboard.players", arg.toString()); - case "teams": - return i.t("scoreboard.teams", arg.toString()); - default: - throw new IllegalArgumentException("Incorrect text type, see javadoc"); - } - } - - /** - * Returns the text displayed in the scoreboard, for the timer. - * - * @param timer The timer to display. - * @param forceNonHoursTimer If true, the non-hours timer text will be returned. - * @param useOldValues if true, the old values of the timer will be used. - * @return The text of the timer. - */ - public String getTimerText(UHTimer timer, Boolean forceNonHoursTimer, Boolean useOldValues) { - Validate.notNull(timer, "The timer cannot be null"); - - if(timer.getDisplayHoursInTimer() && !forceNonHoursTimer) { - if(useOldValues) { - return getTimerText(timer.getOldHoursLeft(), timer.getOldMinutesLeft(), timer.getOldSecondsLeft(), true); - } - else { - return getTimerText(timer.getHoursLeft(), timer.getMinutesLeft(), timer.getSecondsLeft(), true); - } - } - else { - if(useOldValues) { - return getTimerText(0, timer.getOldMinutesLeft(), timer.getOldSecondsLeft(), false); - } - else { - return getTimerText(0, timer.getMinutesLeft(), timer.getSecondsLeft(), false); - } - } - } - - /** - * Returns the text displayed in the scoreboard, for the give values. - * - * @param hours The hours in the timer. - * @param minutes The minutes in the timer. - * @param seconds The seconds in the timer. - * @param displayHours If true, "hh:mm:ss"; else, "mm:ss". - * - * @return The text of the timer. - */ - private String getTimerText(Integer hours, Integer minutes, Integer seconds, Boolean displayHours) { - if(displayHours) { - return i.t("scoreboard.timerWithHours", formatter.format(hours), formatter.format(minutes), formatter.format(seconds)); - } - else { - return i.t("scoreboard.timer", formatter.format(minutes), formatter.format(seconds)); - } - } - - /** - * Updates the health score for all players. - */ - public void updateHealthScore() { - for(final Player player : p.getServer().getOnlinePlayers()) { - updateHealthScore(player); - } - } - - /** - * Updates the health score for the given player. - * - * @param player The player to update. - */ - public void updateHealthScore(final Player player) { - if(player.getHealth() != 1d) { // Prevents killing the player - player.setHealth(player.getHealth() - 1); - - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - if(player.getHealth() <= 19d) { // Avoids an IllegalArgumentException - player.setHealth(player.getHealth() + 1); - } - } - }, 3L); - } - } - - /** - * Tells the player's client to use this scoreboard. - * - * @param p The player. - */ - public void setScoreboardForPlayer(Player p) { - p.setScoreboard(sb); - } - - /** - * Returns the title of the scoreboard, truncated at 32 characters. - * - * @return The name - */ - public String getScoreboardName() { - String s = ChatColor.translateAlternateColorCodes('&', p.getConfig().getString("scoreboard.title", "Kill the Patrick")); - return s.substring(0, Math.min(s.length(), 32)); - } - - /** - * Returns the internal scoreboard. - * - * @return The internal scoreboard. - */ - public Scoreboard getScoreboard() { - return sb; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/scoreboard/SidebarObjective.java b/src/main/java/me/azenet/UHPlugin/scoreboard/SidebarObjective.java deleted file mode 100644 index d2cc756..0000000 --- a/src/main/java/me/azenet/UHPlugin/scoreboard/SidebarObjective.java +++ /dev/null @@ -1,548 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.scoreboard; - -import org.bukkit.scoreboard.DisplaySlot; -import org.bukkit.scoreboard.Objective; -import org.bukkit.scoreboard.Scoreboard; - -import java.util.ArrayList; - -/** - * This class represents a sidebar objective used to display informations - * (aka lines of text). - * <p> - * It manages automatically the scores of the lines (entries), to have the - * smallest positive numbers possible. - * <p> - * <strong>WARNING</strong>: in this class, the <em>index</em> of an entry is - * 0 for the first one (at the top of the sidebar), and <tt>the number of entries - 1</tt> - * for the last one.<br /> - * It is NOT the index used as a score in the objective. - * - * <h3>About separators</h3> - * <em>(<tt>so</tt> is a SidebarObjective object.)</em> - * <p> - * To add a separator (blank line on the sidebar), use - * <tt>so.{@link #addEntry(String) addEntry}(SidebarObjective.SEPARATOR);</tt>.<br /> - * This class will automatically use a different number of spaces to allow you to use - * multiple separators (hard vanilla limit: 17 separators per scoreboard). - * <p> - * To remove a separator, it's a bit more complicated, because separators are not unique. - * <ul> - * <li>If there is only one separator in the scoreboard, you can safely use - * <tt>so.{@link #removeEntry(String) removeEntry}(SidebarObjective.SEPARATOR);</tt>.</li> - * <li>Else, this method will remove the <em>first separator</em> only.<br /> - * To remove a specific separator, use {@link #removeEntryAtIndex(int)}, using the index - * of an entry just before or after the space you want to remove as a reference.<br /> - * this index can be retrieved using - * <tt>so.{@link #getEntryIndex(String) getEntryIndex}("the entry before/after")</tt>.<br /> - * Just add or remove <tt>1</tt> to get the index of the separator. - * </li> - * </ul> - * - * @author Amaury Carrade - */ -public class SidebarObjective { - - private ArrayList<String> entries = new ArrayList<String>(); - - private Scoreboard scoreboard = null; - private String objectiveName = null; - private String displayName = null; - private Objective objective = null; - - /** - * Represents an entry used as a separator. - */ - public static final String SEPARATOR = ""; - - public SidebarObjective(Scoreboard scoreboard, String objectiveName) { - this.objectiveName = objectiveName; - this.scoreboard = scoreboard; - this.displayName = objectiveName; - - registerObjective(); - } - - /** - * Sets the display name of this objective (aka the title of the displayed table). - * - * @param displayName The display name. - */ - public void setDisplayName(String displayName) { - this.displayName = displayName; - setDisplayName(); - } - - /** - * Sets the display name of this objective (aka the title of the displayed table), using the - * stored display name. - * - * Used when the scoreboard is reconstructed. - * - * @param displayName The display name. - */ - private void setDisplayName() { - objective.setDisplayName(displayName.substring(0, Math.min(displayName.length(), 32))); - } - - /** - * Displays the objective on the sidebar. - * - * @throws IllegalStateException If the objective has been unregistered - * with {@link #unregisterObjective()}. - */ - public void display() { - objective.setDisplaySlot(DisplaySlot.SIDEBAR); - } - - /** - * Unregisters the objective. - */ - public void unregisterObjective() { - objective.unregister(); - } - - /** - * Registers the objective. - */ - public void registerObjective() { - this.objective = scoreboard.registerNewObjective(objectiveName, "dummy"); - setDisplayName(); - display(); - } - - - /** - * Adds an entry at the bottom of the sidebar. - * <p> - * An entry is a line in the sidebar.<br /> - * The entry is truncated at 16 characters (Minecraft limitation). - * <p> - * If an entry with this text is already registered, nothing is done. - * - * @param entry The entry to add. - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntry(String entry, boolean dontReconstruct) { - entry = truncateEntry(entry); - - if(!entries.contains(entry) || entry.equals(SEPARATOR)) { // Multiple separators are allowed. - this.entries.add(entry); - - if(!dontReconstruct) reconstruct(); - - return true; - } - - return false; - } - - /** - * Adds an entry at the bottom of the sidebar. - * <p> - * An entry is a line in the sidebar.<br /> - * The entry is truncated at 16 characters (Minecraft limitation). - * <p> - * If an entry with this text is already registered, nothing is done. - * - * @param entry The entry to add. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntry(String entry) { - return addEntry(entry, false); - } - - /** - * Adds an entry at the given index. - * <p> - * Shifts the element currently at that position - * (if any) and any subsequent elements to the bottom - * (adds one to their indexes). - * <p> - * The entry is truncated at 16 characters (Minecraft limitation). - * - * @param index Where - * @param entry What - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryAtIndex(int index, String entry, boolean dontReconstruct) { - entry = truncateEntry(entry); - - if(!entries.contains(entry) || entry.equals(SEPARATOR)) { - ensureSize(entries, index + 1); - entries.add(index, entry); - - if(!dontReconstruct) { - if(index == 0) { // Top - we just need to add a score higher than the other ones. - objective.getScore(entry).setScore(entries.size()); - } - else { - reconstruct(); - } - } - - return true; - } - - return false; - } - - /** - * Adds an entry at the given index. - * <p> - * Shifts the element currently at that position - * (if any) and any subsequent elements to the right - * (adds one to their indices). - * <p> - * The entry is truncated at 16 characters (Minecraft limitation). - * - * @param index Where - * @param entry What - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryAtIndex(int index, String entry) { - return addEntryAtIndex(index, entry, false); - } - - /** - * Adds an entry after the specified entry. - * <p> - * If the string <tt>afterThis</tt> is not registered, the entry is added at the bottom - * of the sidebar. - * <p> - * The entries are truncated at 16 characters (Minecraft limitation). - * - * @param afterThis The entry will be added after this entry. Don't use a separator for this! - * @param entry The entry to add. - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryAfter(String afterThis, String entry, boolean dontReconstruct) { - entry = truncateEntry(entry); - - if(!entries.contains(entry) || entry.equals(SEPARATOR)) { - int beforeIndex = entries.indexOf(truncateEntry(afterThis)); - - if(beforeIndex == -1 || beforeIndex == entries.size()) { - return addEntry(entry, dontReconstruct); - } - - addEntryAtIndex(beforeIndex + 1, entry, dontReconstruct); - - return true; - } - - return false; - } - - /** - * Adds an entry after the specified entry. - * <p> - * If the string <tt>afterThis</tt> is not registered, the entry is added at the bottom - * of the sidebar. - * <p> - * The entries are truncated at 16 characters (Minecraft limitation). - * - * @param afterThis The entry will be added after this entry. - * @param entry The entry to add. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryAfter(String afterThis, String entry) { - return addEntryAfter(afterThis, entry, false); - } - - /** - * Adds an entry before the specified entry. - * <p> - * If the string <tt>beforeThis</tt> is not registered, the entry is added at the top - * of the sidebar. - * <p> - * The entries are truncated at 16 characters (Minecraft limitation). - * - * @param beforeThis The entry will be added before this entry. - * @param entry The entry to add. - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryBefore(String beforeThis, String entry, boolean dontReconstruct) { - entry = truncateEntry(entry); - - if(!entries.contains(entry) || entry.equals(SEPARATOR)) { - int afterIndex = entries.indexOf(truncateEntry(beforeThis)); - - if(afterIndex == -1 || afterIndex == entries.size()) { - return addEntryAtIndex(0, entry, dontReconstruct); - } - - addEntryAtIndex(afterIndex - 1, entry, dontReconstruct); - - return true; - } - - return false; - } - - /** - * Adds an entry before the specified entry. - * <p> - * If the string <tt>beforeThis</tt> is not registered, the entry is added at the top - * of the sidebar. - * <p> - * The entry are truncated at 16 characters (Minecraft limitation). - * - * @param beforeThis The entry will be added before this entry. - * @param entry The entry to add. - * - * @return <tt>True</tt> if the entry was added (aka non already registered). - */ - public boolean addEntryBefore(String beforeThis, String entry) { - return addEntryBefore(beforeThis, entry, false); - } - - /** - * Updates the entry <tt>oldEntry</tt> with the text <tt>newEntry</tt>. - * <p> - * The entries are truncated at 16 characters (Minecraft limitation). - * - * @param oldEntry The text to be updated. Don't use a separator here! - * @param newEntry The updated text. - * - * @return <tt>True</tt> if the text was updated (aka <tt>true</tt> if an - * entry <tt>oldEntry</tt> is registered). - */ - public boolean updateEntry(String oldEntry, String newEntry) { - int index = entries.indexOf(oldEntry); - if(index != -1) { - entries.set(index, newEntry); - - int score = objective.getScore(oldEntry).getScore(); - scoreboard.resetScores(oldEntry); - objective.getScore(newEntry).setScore(score); - - return true; - } - - return false; - } - - - /** - * Removes the entry at the given index from the sidebar. - * - * @param index The index of the entry to remove. - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if an entry was removed. - */ - public boolean removeEntryAtIndex(int index, boolean dontReconstruct) { - try { - if(entries.get(index) != null) { - entries.remove(index); - if(!dontReconstruct) reconstruct(); - return true; - } - } catch(ArrayIndexOutOfBoundsException e) { - // Entry not defined - } - - return false; - } - - /** - * Removes the entry at the given index from the sidebar. - * - * @param index The index of the entry to remove. - * - * @return <tt>True</tt> if an entry was removed. - */ - public boolean removeEntryAtIndex(int index) { - return removeEntryAtIndex(index, false); - } - - /** - * Removes the given entry from the sidebar. - * <p> - * The entry is truncated at 16 characters (Minecraft limitation). - * - * @param entry The entry to remove. - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - * - * @return <tt>True</tt> if an entry was removed. - */ - public boolean removeEntry(String entry, boolean dontReconstruct) { - return removeEntryAtIndex(entries.indexOf(entry), dontReconstruct); - } - - /** - * Removes the given entry from the sidebar. - * <p> - * The entry is truncated at 16 characters (Minecraft limitation). - * - * @param entry The entry to remove. - * - * @return <tt>True</tt> if an entry was removed. - */ - public boolean removeEntry(String entry) { - return removeEntry(entry, false); - } - - - /** - * Resets the sidebar, removing all entries. - * - * @param dontReconstruct If true, the objective will not been automatically - * reconstructed. You will need to call {@link #reconstruct()} to do so. - */ - public void reset(boolean dontReconstruct) { - entries.clear(); - - if(!dontReconstruct) reconstruct(); - } - - /** - * Resets the sidebar, removing all entries. - */ - public void reset() { - reset(false); - } - - - /** - * Returns the index of the given entry. - * <p> - * The entry is truncated at 16 characters (Minecraft limitation). - * - * @param entry The entry. - * @return The index, or {@code -1} if the given {@code entry} is not registered. - */ - public int getEntryIndex(String entry) { - return entries.indexOf(truncateEntry(entry)); - } - - /** - * Returns the (truncated) entry at the given index. - * - * @param index The index. - * @return The entry. - */ - public String getEntry(int index) { - return entries.get(index); - } - - - /** - * Reconstructs the sidebar from scratch, with recalculated scores - * following the number of entries. - * Automatically called when an entry is added/removed, except if the reconstruction - * is explicitly disabled using the dontReconstruct parameter. - */ - public void reconstruct() { - // First: the objective is removed, then recreated, to reset it. - this.unregisterObjective(); - this.registerObjective(); - - // We don't want a "0" score, because these scores need a special - // initialization (set to 1, and to 0 one tick later). - int score = entries.size(); - int maxScore = score; - - // We use this to generate a different number of spaces for each separator. - int separatorSpacesCount = 0; - - for(int i = 0 ; i < maxScore ; i++) { - String entry = entries.get(i); - - if(entry == null) continue; - - if(entry.equals(SEPARATOR)) { - objective.getScore(generateSpaces(separatorSpacesCount)).setScore(score); - separatorSpacesCount++; - } - else { - objective.getScore(entries.get(i)).setScore(score); - } - - score--; - } - } - - - /** - * Truncates the given entry at 16 characters, the maximal size allowed by - * Minecraft. - * - * @param entry The entry to truncate. - * @return The truncated entry. - */ - private String truncateEntry(String entry) { - return entry.substring(0, Math.min(entry.length(), 16)); - } - - /** - * Generates a string containing {@code spaces} spaces. - * - * @param spaces The number of spaces in the string. - * - * @return The string. - */ - protected String generateSpaces(int spaces) { - String space = ""; - - for(int i = 0; i < spaces; i++) { - space += " "; - } - - return space; - } - - /** - * Increases the size of the given {@code ArrayList} if needed. - * - * @param list The list. - * @param size The size. - */ - private void ensureSize(ArrayList<?> list, int size) { - if(list.size() < size) { - // Prevent excessive copying while we're adding - list.ensureCapacity(size); - - while (list.size() < size) { - list.add(null); - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/Generator.java b/src/main/java/me/azenet/UHPlugin/spawns/Generator.java deleted file mode 100644 index 7ace53d..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/Generator.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.spawns; - - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.spawns.generators.CircularSpawnPointsGenerator; -import me.azenet.UHPlugin.spawns.generators.GridSpawnPointsGenerator; -import me.azenet.UHPlugin.spawns.generators.RandomSpawnPointsGenerator; -import me.azenet.UHPlugin.spawns.generators.SpawnPointsGenerator; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; - - -public enum Generator { - - /** - * Spawn points generated randomly. - */ - RANDOM(RandomSpawnPointsGenerator.class), - - /** - * Spawn points generated following the shape of a grid, - * with concentric squares (starting from the largest square). - */ - GRID(GridSpawnPointsGenerator.class), - - /** - * Spawn points generated on concentric circles (starting from the - * largest circle). - */ - CIRCULAR(CircularSpawnPointsGenerator.class); - - - private Class<? extends SpawnPointsGenerator> generatorClass; - - /** - * @param generatorClass The generator. - */ - Generator(Class<? extends SpawnPointsGenerator> generatorClass) { - this.generatorClass = generatorClass; - } - - /** - * Returns a new instance of the generator. - * - * @return The instance. - */ - public SpawnPointsGenerator getInstance(UHPlugin p) { - - try { - Constructor constructor = generatorClass.getConstructor(UHPlugin.class); - return (SpawnPointsGenerator) constructor.newInstance(p); - - } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException e) { - p.getLogger().log(Level.SEVERE, "Cannot instantiate the spawn points generator: invalid class (missing constructor?)."); - e.printStackTrace(); - return null; - } - } - - /** - * Returns a generator based on his name. - * - * <p>Not case sensitive.</p> - * - * @param name The name. - * @return The Generator, or null if not found. - */ - public static Generator fromString(String name) { - try { - return Generator.valueOf(name.trim().toUpperCase()); - } catch(IllegalArgumentException e) { - return null; - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/SpawnsManager.java b/src/main/java/me/azenet/UHPlugin/spawns/SpawnsManager.java deleted file mode 100644 index 9da0de2..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/SpawnsManager.java +++ /dev/null @@ -1,253 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.spawns; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import me.azenet.UHPlugin.spawns.exceptions.UnknownGeneratorException; -import me.azenet.UHPlugin.spawns.generators.SpawnPointsGenerator; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.World.Environment; - -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -public class SpawnsManager { - - UHPlugin p = null; - I18n i = null; - - private LinkedList<Location> spawnPoints = new LinkedList<Location>(); - - private boolean avoidWater; - - - public SpawnsManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - - avoidWater = p.getConfig().getBoolean("map.spawnPoints.dontGenerateAboveWater"); - } - - /** - * Adds a spawn point at (x;z) in the default world. - * - * @param x The X coordinate. - * @param z The Z coordinate. - */ - public void addSpawnPoint(final Double x, final Double z) { - addSpawnPoint(p.getServer().getWorlds().get(0), x, z); - } - - /** - * Adds a spawn point at (x;z) in the given world. - * - * @param world The world. - * @param x The X coordinate. - * @param z The Z coordinate. - */ - public void addSpawnPoint(final World world, final Double x, final Double z) { - addSpawnPoint(new Location(world, x, 0, z)); - } - - /** - * Adds a spawn point from a location. - * - * @param location The location. Cloned, so you can use the same location object with - * modifications between two calls. - * - * @throws RuntimeException If the spawn point is in the Nether and no safe spot was found. - * @throws IllegalArgumentException If the spawn point is out of the current border. - */ - public void addSpawnPoint(final Location location) { - Location spawnPoint = location.clone(); - - // Initial fall, except in the nether. - if(!(spawnPoint.getWorld().getEnvironment() == Environment.NETHER)) { - spawnPoint.setY(location.getWorld().getHighestBlockYAt(location.getBlockX(), location.getBlockZ()) + 120); - } - else { - Location safeSpot = UHUtils.searchSafeSpot(location); - if(safeSpot == null) { - throw new RuntimeException("Unable to find a safe spot to set the spawn point " + location.toString()); - } - - spawnPoint.setY(safeSpot.getY()); - } - - if(!p.getBorderManager().isInsideBorder(spawnPoint)) { - throw new IllegalArgumentException("The given spawn location is outside the current border"); - } - - spawnPoints.add(spawnPoint); - } - - /** - * Returns the registered spawn points. - * - * @return The spawn points. - */ - public List<Location> getSpawnPoints() { - return spawnPoints; - } - - /** - * Removes all spawn points with the same coordinates as the given location object - * (X, Z, world). - * - * @param location The location to be removed. - * @param precise If true, only the spawn points at the exact same location will be removed. - * Else, the points in the same block. - * @return true if something were removed. - */ - public boolean removeSpawnPoint(Location location, boolean precise) { - List<Location> toRemove = new LinkedList<Location>(); - - for(Location spawn : getSpawnPoints()) { - if(location.getWorld().equals(spawn.getWorld())) { - if(precise - && location.getX() == spawn.getX() - && location.getZ() == spawn.getZ()) { - toRemove.add(spawn); - } - else if(!precise - && location.getBlockX() == spawn.getBlockX() - && location.getBlockZ() == spawn.getBlockZ()) { - toRemove.add(spawn); - } - } - } - - for(Location spawnToRemove : toRemove) { - while(spawnPoints.remove(spawnToRemove)); // Used to remove all occurrences of the spawn point - } - - return toRemove.size() != 0; - } - - /** - * Removes all registered spawn points. - * - * CANNOT BE CANCELLED. - */ - public void reset() { - spawnPoints = new LinkedList<Location>(); - } - - - /** - * Imports spawn points from the configuration. - * - * @return The number of spawn points imported. - */ - public int importSpawnPointsFromConfig() { - if(p.getConfig().getList("spawnpoints") != null) { - int spawnCount = 0; - for(Object position : p.getConfig().getList("spawnpoints")) { - if(position instanceof String && position != null) { - String[] coords = ((String) position).split(","); - try { - addSpawnPoint(Double.parseDouble(coords[0]), Double.parseDouble(coords[1])); - p.getLogger().info(i.t("load.spawnPointAdded", coords[0], coords[1])); - spawnCount++; - } catch(Exception e) { // Not an integer or not enough coords - p.getLogger().warning(i.t("load.invalidSpawnPoint", (String) position)); - } - } - } - - return spawnCount; - } - - return 0; - } - - - /** - * Generates spawn points with the given generator. - * - * @param generatorName The generator to use. - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * - * @throws me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException In case of fail. - */ - public void generateSpawnPoints(String generatorName, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException, UnknownGeneratorException { - Generator generator = Generator.fromString(generatorName); - if(generator != null) { - generateSpawnPoints(generator, world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter); - } - else { - throw new UnknownGeneratorException("The generator '" + generatorName + "' does not exists."); - } - } - - /** - * Generates spawn points with the given generator. - * - * @param generator The generator to use. - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * - * @throws CannotGenerateSpawnPointsException In case of fail. - */ - public void generateSpawnPoints(Generator generator, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException { - generateSpawnPoints(generator.getInstance(p), world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter); - } - - /** - * Generates spawn points with the given generator. - * - * @param generator The generator to use. - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * - * @throws CannotGenerateSpawnPointsException In case of fail. - */ - public void generateSpawnPoints(SpawnPointsGenerator generator, World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter) throws CannotGenerateSpawnPointsException { - Set<Location> spawnPoints = generator.generate(world, spawnCount, regionDiameter, minimalDistanceBetweenTwoPoints, xCenter, zCenter, avoidWater); - - for(Location spawn : spawnPoints) { - addSpawnPoint(spawn); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/exceptions/CannotGenerateSpawnPointsException.java b/src/main/java/me/azenet/UHPlugin/spawns/exceptions/CannotGenerateSpawnPointsException.java deleted file mode 100644 index b4d0e0a..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/exceptions/CannotGenerateSpawnPointsException.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.spawns.exceptions; - - -public class CannotGenerateSpawnPointsException extends Exception { - - public CannotGenerateSpawnPointsException(String message) { - super(message); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/exceptions/UnknownGeneratorException.java b/src/main/java/me/azenet/UHPlugin/spawns/exceptions/UnknownGeneratorException.java deleted file mode 100644 index c74c3c3..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/exceptions/UnknownGeneratorException.java +++ /dev/null @@ -1,8 +0,0 @@ -package me.azenet.UHPlugin.spawns.exceptions; - -public class UnknownGeneratorException extends Exception { - - public UnknownGeneratorException(String message) { - super(message); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/generators/GridSpawnPointsGenerator.java b/src/main/java/me/azenet/UHPlugin/spawns/generators/GridSpawnPointsGenerator.java deleted file mode 100644 index 8630e1c..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/generators/GridSpawnPointsGenerator.java +++ /dev/null @@ -1,165 +0,0 @@ -package me.azenet.UHPlugin.spawns.generators; - - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.MapShape; -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; - -import java.util.HashSet; -import java.util.Set; - -public class GridSpawnPointsGenerator implements SpawnPointsGenerator { - - private UHPlugin p; - - public GridSpawnPointsGenerator(UHPlugin p) { - this.p = p; - } - - /** - * Generates spawn points in a grid. - * - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * @param avoidWater True if the generation have to avoid the water. - * - * @return The spawn points generated. - * - * @throws CannotGenerateSpawnPointsException In case of fail. - */ - @Override - public Set<Location> generate(World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter, boolean avoidWater) throws CannotGenerateSpawnPointsException { - - // We starts the generation on a smaller grid, to avoid false outside tests if the point is on the edge - int usedRegionDiameter = regionDiameter - 1; - - // To check the possibility of the generation, we calculates the maximal number of columns/rows - // possible, based on the minimal distance between two points. - int maxColumnsCount = (int) Math.ceil(usedRegionDiameter / minimalDistanceBetweenTwoPoints); - - // The points are on a grid - int neededColumnsCount = (int) Math.ceil(Math.sqrt(spawnCount)); - if (p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - // If the border is circular, the distance between two points needs to be decreased. - // The space available is divided by PI/4, so the column count is multiplied by - // this number. - neededColumnsCount = (int) Math.ceil(neededColumnsCount / (Math.PI / 4)); - } - - // IS impossible. - if (neededColumnsCount > maxColumnsCount) { - throw new CannotGenerateSpawnPointsException("Cannot generate spawn points on a grid: not enough space."); - } - // If the map is circular, the generation may be impossible, because this check was - // performed for a squared map. - // The test will be done after the generation. - - - // We generates the points on a grid in squares, starting by the biggest square. - int distanceBetweenTwoPoints = (int) (Double.valueOf(usedRegionDiameter) / (Double.valueOf(neededColumnsCount - 1))); - - // Check related to the case the column count was increased. - if (distanceBetweenTwoPoints < minimalDistanceBetweenTwoPoints) { - throw new CannotGenerateSpawnPointsException("Cannot generate spawn points on a grid: not enough space."); - } - - - int countGeneratedPoints = 0; - HashSet<Location> generatedPoints = new HashSet<Location>(); - - int halfDiameter = (int) Math.floor(usedRegionDiameter / 2); - - Integer currentSquareSize = usedRegionDiameter; - Location currentSquareStartPoint = new Location(world, xCenter + halfDiameter, 0, zCenter - halfDiameter); - Location currentPoint; - - // Represents the location to add on each side of the squares - Location[] addOnSide = new Location[4]; - addOnSide[0] = new Location(world, -distanceBetweenTwoPoints, 0, 0); // North side, direction east - addOnSide[1] = new Location(world, 0, 0, distanceBetweenTwoPoints); // East side, direction south - addOnSide[2] = new Location(world, distanceBetweenTwoPoints, 0, 0); // South side, direction west - addOnSide[3] = new Location(world, 0, 0, -distanceBetweenTwoPoints); // West side, direction north - - // We generates the points until there isn't any point left to place. The loop will be broken. - // On each step of this loop, a square is generated. - generationLoop: - while (true) { - currentPoint = currentSquareStartPoint.clone(); - - // First point - if (p.getBorderManager().isInsideBorder(currentPoint, regionDiameter) && UHUtils.searchSafeSpot(currentPoint) != null) { - generatedPoints.add(currentPoint.clone()); - countGeneratedPoints++; - - if (countGeneratedPoints >= spawnCount) { - break generationLoop; - } - } - - for (int j = 0; j < 4; j++) { // A step for each side, j is the side (see addOnSide). - int plottedSize = 0; - - sideLoop: - while (plottedSize < currentSquareSize) { - currentPoint.add(addOnSide[j]); - plottedSize += distanceBetweenTwoPoints; - - // Inside the border? - if (!p.getBorderManager().isInsideBorder(currentPoint, regionDiameter)) { - continue sideLoop; - } - - Block surfaceBlock = world.getHighestBlockAt(currentPoint); - - // Safe spot available? - if (!UHUtils.isSafeSpot(surfaceBlock.getLocation())) { - continue sideLoop; // not safe: nope - } - - // Not above the water? - if (avoidWater) { - if (surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) { - continue sideLoop; - } - } - - generatedPoints.add(currentPoint.clone()); - countGeneratedPoints++; - - if (countGeneratedPoints >= spawnCount) { - break generationLoop; - } - } - } - - // This square is complete; preparing the next one... - currentSquareSize -= 2 * distanceBetweenTwoPoints; - currentSquareStartPoint.add(new Location(world, -distanceBetweenTwoPoints, 0, distanceBetweenTwoPoints)); - - if (currentSquareSize < distanceBetweenTwoPoints) { - // This may happens if we generates the points for a circular world - break generationLoop; - } - } - - // If the generation was broken (circular world, not enough positions), - // the generation was incomplete. - if (countGeneratedPoints >= spawnCount) { - // Generation OK - return generatedPoints; - } else { - throw new CannotGenerateSpawnPointsException("Cannot generate the spawn points: not enough space."); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/generators/RandomSpawnPointsGenerator.java b/src/main/java/me/azenet/UHPlugin/spawns/generators/RandomSpawnPointsGenerator.java deleted file mode 100644 index 7d6da9c..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/generators/RandomSpawnPointsGenerator.java +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.spawns.generators; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.MapShape; -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; - -import java.util.HashSet; -import java.util.Random; -import java.util.Set; - -/** - * Generates the spawn points randomly. - */ -public class RandomSpawnPointsGenerator implements SpawnPointsGenerator { - - private UHPlugin p; - - public RandomSpawnPointsGenerator(UHPlugin p) { - this.p = p; - } - - /** - * Generates randomly some spawn points in the map, with a minimal distance. - * - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * @param avoidWater True if the generation have to avoid the water. - * - * @return The spawn points generated. - * - * @throws CannotGenerateSpawnPointsException In case of fail - */ - @Override - public Set<Location> generate(World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter, boolean avoidWater) throws CannotGenerateSpawnPointsException { - /** Possible? **/ - - // If the surface of the map is too close of the sum of the surfaces of the private part - // around each spawn point (a circle with, as radius, the minimal distance between two spawn - // points), the generation will fail. - - double surfacePrivatePartsAroundSpawnPoints = (int) (spawnCount * (Math.PI * Math.pow(minimalDistanceBetweenTwoPoints, 2))); - double surfaceRegion; - if(p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - surfaceRegion = (Math.PI * Math.pow(regionDiameter, 2)) / 4; - } - else { - surfaceRegion = Math.pow(regionDiameter, 2); - } - - Double packingDensity = surfacePrivatePartsAroundSpawnPoints / surfaceRegion; - - // According to Lagrange and Thue's works on circle packagings, the highest density possible is - // approximately 0.9069 (with an hexagonal arrangement of the circles). - // Even with a packaging density very close to this limit, the generation time is correct. - // So we uses this as a limit. - if(packingDensity >= 0.9069) { - throw new CannotGenerateSpawnPointsException("Unable to generate spawn points randomly: packing density too high"); - } - - /** Generation **/ - - Set<Location> randomSpawnPoints = new HashSet<Location>(); - int generatedSpawnPoints = 0; - - // If the first points are badly located, and if the density is high, the generation may - // be impossible to end. - // So, after 15 generation fails of a point due to this point being placed too close - // of other ones, we restarts all the generation. - int currentErrorCount = 0; - - // With the "avoid above water" option, if there's a lot of water, the genaration may - // fail even if the surface seems to be ok to host the requested spawn points. - // So, after 2*{points requested} points above the water, we cancels the generation. - int pointsAboveWater = 0; - - generationLoop: while(generatedSpawnPoints != spawnCount) { - - // "Too many fails" test - if(currentErrorCount >= 16) { // restart - randomSpawnPoints = new HashSet<Location>(); - generatedSpawnPoints = 0; - currentErrorCount = 0; - } - - // "Too many points above the water" test - if(pointsAboveWater >= 2*spawnCount) { - throw new CannotGenerateSpawnPointsException("Too many spawn points above the water."); - } - - - // We generates a point in the square of side regionDiameter. - // In case of a circular world, if the point was generated out of the circle, it will be - // excluded when his presence inside the region will be checked. - - Location randomPoint = new Location(world, - random((int) (xCenter - Math.floor(regionDiameter / 2)), (int) (xCenter + (int) Math.floor(regionDiameter / 2))), - 0, - random((int) (zCenter - Math.floor(regionDiameter / 2)), (int) (zCenter + (int) Math.floor(regionDiameter / 2)))); - - // Inside the region? - if(!p.getBorderManager().isInsideBorder(randomPoint, regionDiameter)) { - continue generationLoop; // outside: nope - } - - Block surfaceBlock = world.getHighestBlockAt(randomPoint); - - // Safe spot available? - if(!UHUtils.isSafeSpot(surfaceBlock.getLocation())) { - continue generationLoop; // not safe: nope - } - - // Not above the water? - if(avoidWater) { - if(surfaceBlock.getType() == Material.WATER || surfaceBlock.getType() == Material.STATIONARY_WATER) { - pointsAboveWater++; - continue generationLoop; - } - } - - // Is that point at a correct distance of the other ones? - for(Location spawn : randomSpawnPoints) { - if(spawn.distance(randomPoint) < minimalDistanceBetweenTwoPoints) { - currentErrorCount++; - continue generationLoop; // too close: nope - } - } - - // Well, all done. - randomSpawnPoints.add(randomPoint); - generatedSpawnPoints++; - currentErrorCount = 0; - } - - // Generation done, let's register these points. - - return randomSpawnPoints; - } - - - /** - * Generates a random number between min and max. - * - * @param min The minimum value. May be negative. Inclusive. - * @param max The maximum value. May be negative. Inclusive. - * @return A random number between these two points. - */ - public Integer random(int min, int max) { - if(min == max) { - return min; - } - - Random rand = new Random(); - - if(min > max) { // swap - min = min + max; - max = min - max; - min = min - max; - } - - if(min >= 0 && max >= 0) { - return rand.nextInt(max - min + 1) + min; - } - else if(min <= 0 && max <= 0) { - return -1 * (rand.nextInt(Math.abs(min - max)) + Math.abs(max)); - } - else { // min <= 0 && max >= 0 - return rand.nextInt(Math.abs(min) + Math.abs(max)) - Math.abs(min); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/spawns/generators/SpawnPointsGenerator.java b/src/main/java/me/azenet/UHPlugin/spawns/generators/SpawnPointsGenerator.java deleted file mode 100644 index 3fc8983..0000000 --- a/src/main/java/me/azenet/UHPlugin/spawns/generators/SpawnPointsGenerator.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.spawns.generators; - - -import me.azenet.UHPlugin.spawns.exceptions.CannotGenerateSpawnPointsException; -import org.bukkit.Location; -import org.bukkit.World; - -import java.util.Set; - - -/** - * Represents a spawn points generator. - * - * <p> - * The constructor must take a single argument, an instance of the main class of - * the plugin. - * </p> - */ -public interface SpawnPointsGenerator { - - /** - * Generates the spawn points. - * - * @param world The world where the spawn points will be generated. - * @param spawnCount The number of spawn points to generate. - * @param regionDiameter The diameter of the region where the spawn points will be generated.<br> - * This is limited by the size of the map. This will be seen as the diameter of a circular or - * of a squared map, following the shape of the world set in the configuration. - * @param minimalDistanceBetweenTwoPoints The minimal distance between two points. - * @param xCenter The x coordinate of the point in the center of the region where the points will be generated. - * @param zCenter The z coordinate of the point in the center of the region where the points will be generated. - * @param avoidWater True if the generation have to avoid the water. - * - * @return The spawn points generated. - * - * @throws CannotGenerateSpawnPointsException In case of fail. - */ - public Set<Location> generate(World world, int spawnCount, int regionDiameter, int minimalDistanceBetweenTwoPoints, double xCenter, double zCenter, boolean avoidWater) throws CannotGenerateSpawnPointsException; - -} diff --git a/src/main/java/me/azenet/UHPlugin/task/BorderWarningTask.java b/src/main/java/me/azenet/UHPlugin/task/BorderWarningTask.java deleted file mode 100644 index ef693f8..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/BorderWarningTask.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.borders.MapShape; -import me.azenet.UHPlugin.i18n.I18n; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -public class BorderWarningTask extends BukkitRunnable { - - private UHPlugin p = null; - private I18n i = null; - - public BorderWarningTask(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - } - - @Override - public void run() { - - if(p.getFreezer().getGlobalFreezeState()) { - return; // No messages are sent if the game is frozen. - } - - // Message sent to all players outside the border - for(Player player : p.getBorderManager().getPlayersOutside(p.getBorderManager().getWarningSize())) { - double distance = p.getBorderManager().getDistanceToBorder(player.getLocation(), p.getBorderManager().getWarningSize()); - - if(p.getBorderManager().getMapShape() == MapShape.CIRCULAR) { - player.sendMessage(i.t("borders.warning.messageCircular", String.valueOf(p.getBorderManager().getWarningSize()))); - } - else { - player.sendMessage(i.t("borders.warning.messageSquared", String.valueOf(p.getBorderManager().getWarningSize()))); - } - - player.sendMessage(i.t("borders.warning.messageDistance", String.valueOf(distance))); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/task/CancelBrewTask.java b/src/main/java/me/azenet/UHPlugin/task/CancelBrewTask.java deleted file mode 100644 index a7eb607..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/CancelBrewTask.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.BrewerInventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; - -public class CancelBrewTask extends BukkitRunnable { - - private BrewerInventory inventory = null; - private HumanEntity whoClicked = null; - - public CancelBrewTask(BrewerInventory inventory, HumanEntity whoClicked) { - this.inventory = inventory; - this.whoClicked = whoClicked; - } - - @Override - public void run() { - if(inventory.getIngredient() == null) { - return; // Nothing to do! - } - - if(whoClicked instanceof Player) { - ItemStack ingredient = inventory.getIngredient(); - - if(ingredient.getType() != null && ingredient.getType().equals(Material.GLOWSTONE_DUST)) { - inventory.setIngredient(new ItemStack(Material.AIR)); // The glowstone is removed. - - // First try: try to add the glowstone to an existing stack - Boolean added = false; - for(ItemStack item : whoClicked.getInventory().getContents()) { - if(item != null && item.getType() != null && item.getType().equals(Material.GLOWSTONE_DUST)) { - if(item.getAmount() + ingredient.getAmount() <= item.getMaxStackSize()) { - // We can add the glowstone here. - item.setAmount(item.getAmount() + ingredient.getAmount()); - added = true; - break; - } - } - } - - if(!added) { - // Failed... We adds the glowstone to the first empty slot found. - - Integer slotEmpty = whoClicked.getInventory().firstEmpty(); - - if(slotEmpty != -1) { // -1 is returned if there isn't any empty slot - whoClicked.getInventory().setItem(slotEmpty, ingredient); - } - else { - // Failed again (!). Maybe an item captured between the click and this execution. - // The stack is dropped at the player's location. - whoClicked.getWorld().dropItem(whoClicked.getLocation(), ingredient); - } - } - - ((Player) whoClicked).updateInventory(); - } - } - } - -} diff --git a/src/main/java/me/azenet/UHPlugin/task/FireworksOnWinnersTask.java b/src/main/java/me/azenet/UHPlugin/task/FireworksOnWinnersTask.java deleted file mode 100644 index bd413ee..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/FireworksOnWinnersTask.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.Location; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.Random; -import java.util.Set; - -public class FireworksOnWinnersTask extends BukkitRunnable { - - private UHPlugin p = null; - private Set<OfflinePlayer> winners = null; - - private Double areaSize; - private Random rand; - - private long startTime = 0L; - - public FireworksOnWinnersTask(UHPlugin p, Set<OfflinePlayer> listWinners) { - this.p = p; - this.winners = listWinners; - - this.areaSize = p.getConfig().getDouble("finish.fireworks.areaSize"); - this.rand = new Random(); - - this.startTime = System.currentTimeMillis(); - } - - @Override - public void run() { - // The fireworks are launched in a square centered on the player. - Double halfAreaSize = areaSize / 2; - - for(OfflinePlayer winner : winners) { - if(winner.isOnline()) { - Location fireworkLocation = ((Player) winner).getLocation(); - - fireworkLocation.add(rand.nextDouble() * areaSize - halfAreaSize, // a number between -halfAreaSize and halfAreaSize - 2, // y+2 for a clean vision of the winner. - rand.nextDouble() * areaSize - halfAreaSize); - - UHUtils.generateRandomFirework(fireworkLocation, 0, 15); - UHUtils.generateRandomFirework(fireworkLocation.add(0.2, 0d, 0.2), 0, 15); - UHUtils.generateRandomFirework(fireworkLocation.add(-0.2, 0d, 0.2), 0, 15); - } - } - - if((System.currentTimeMillis() - startTime) / 1000 > p.getConfig().getInt("finish.fireworks.duration", 10)) { - this.cancel(); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/task/ScheduledCommandsExecutorTask.java b/src/main/java/me/azenet/UHPlugin/task/ScheduledCommandsExecutorTask.java deleted file mode 100644 index 82b4fbc..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/ScheduledCommandsExecutorTask.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import me.azenet.UHPlugin.UHPlugin; -import org.bukkit.command.CommandException; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.HashSet; -import java.util.logging.Level; - -/** - * Schedules a stack of commands executed at the same time. - */ -public class ScheduledCommandsExecutorTask extends BukkitRunnable { - - UHPlugin p = null; - HashSet<String> commands = null; - - public ScheduledCommandsExecutorTask(UHPlugin plugin, HashSet<String> commands) { - this.p = plugin; - this.commands = commands; - } - - @Override - public void run() { - for(String command : commands) { - try { - p.getServer().dispatchCommand(p.getServer().getConsoleSender(), command); - } catch(CommandException e) { - p.getLogger().log(Level.WARNING, "The scheduled command '" + command + "' failed.", e); - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/task/TeamStartTask.java b/src/main/java/me/azenet/UHPlugin/task/TeamStartTask.java deleted file mode 100644 index 6252273..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/TeamStartTask.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Plugin UltraHardcore (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.teams.UHTeam; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.potion.PotionEffect; -import org.bukkit.scheduler.BukkitRunnable; - -public class TeamStartTask extends BukkitRunnable { - - private UHPlugin p = null; - private I18n i = null; - private UHTeam team = null; - private Location startPoint = null; - private Boolean slow = false; - private CommandSender sender = null; - private Integer teamsTeleported = 0; - - public TeamStartTask(UHPlugin p, UHTeam team, Location startPoint) { - this.p = p; - this.i = p.getI18n(); - this.team = team; - this.startPoint = startPoint; - } - - public TeamStartTask(UHPlugin p, UHTeam team, Location startPoint, Boolean slow, CommandSender sender, Integer teamsTeleported) { - this.p = p; - this.i = p.getI18n(); - this.team = team; - this.startPoint = startPoint; - this.slow = slow; - this.sender = sender; - this.teamsTeleported = teamsTeleported; - } - - @Override - public void run() { - team.teleportTo(startPoint); - - for (Player player : team.getOnlinePlayers()) { - player.setGameMode(GameMode.SURVIVAL); - - if(slow) { - player.setAllowFlight(true); - player.setFlying(true); - } - - player.setHealth(20D); - player.setFoodLevel(20); - player.setSaturation(20); - player.getInventory().clear(); - player.getInventory().setArmorContents(new ItemStack[] {new ItemStack(Material.AIR), new ItemStack(Material.AIR), new ItemStack(Material.AIR), new ItemStack(Material.AIR)}); - player.setExp(0L+0F); - player.setLevel(0); - player.closeInventory(); - for(PotionEffect effect : player.getActivePotionEffects()) { - player.removePotionEffect(effect.getType()); - } - player.setCompassTarget(startPoint); - } - - p.getDynmapIntegration().showSpawnLocation(team, startPoint); - - if(slow) { - try { - sender.sendMessage(i.t("start.startSlowTeamTP", team.getDisplayName())); - } catch(NullPointerException e) { } - - if(p.getGameManager().getAliveTeamsCount() == this.teamsTeleported) { - p.getGameManager().setSlowStartTPFinished(true); - - try { - sender.sendMessage(i.t("start.startSlowAllTeamsTP")); - sender.sendMessage(i.t("start.startSlowAllTeamsTPCmd")); - } catch(NullPointerException e) { } - } - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/task/UpdateTimerTask.java b/src/main/java/me/azenet/UHPlugin/task/UpdateTimerTask.java deleted file mode 100644 index 6bbbf6f..0000000 --- a/src/main/java/me/azenet/UHPlugin/task/UpdateTimerTask.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.task; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.timers.UHTimer; -import org.bukkit.scheduler.BukkitRunnable; - -public class UpdateTimerTask extends BukkitRunnable { - - private UHPlugin p = null; - - public UpdateTimerTask(UHPlugin p) { - this.p = p; - } - - @Override - public void run() { - - for(UHTimer timer : p.getTimerManager().getRunningTimers()) { - timer.update(); - } - - p.getScoreboardManager().updateTimers(); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/teams/TeamChatManager.java b/src/main/java/me/azenet/UHPlugin/teams/TeamChatManager.java deleted file mode 100644 index 3599872..0000000 --- a/src/main/java/me/azenet/UHPlugin/teams/TeamChatManager.java +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.teams; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.misc.ProTipsSender; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.*; - -public class TeamChatManager { - - UHPlugin p = null; - I18n i = null; - - List<UUID> teamChatLocked = new ArrayList<UUID>(); - Map<UUID,UHTeam> otherTeamChatLocked = new HashMap<UUID,UHTeam>(); - - public TeamChatManager(UHPlugin p) { - this.p = p; - this.i = p.getI18n(); - } - - /** - * Sends a team-message from the given sender. - * - * @param sender The sender. - * @param message The message to send. - */ - public void sendTeamMessage(Player sender, String message) { - sendTeamMessage(sender, message, null); - } - - /** - * Sends a team-message from the given sender. - * - * @param sender The sender. - * @param message The message to send. - * @param team If not null, this message will be considered as an external message from another player to this team. - */ - public void sendTeamMessage(Player sender, String message, UHTeam team) { - - // Permission check - if(team == null && !sender.hasPermission("uh.teamchat.self")) { - sender.sendMessage(i.t("team.message.notAllowed.self")); - return; - } - if(team != null && !sender.hasPermission("uh.teamchat.others")) { - sender.sendMessage(i.t("team.message.notAllowed.others")); - return; - } - - String rawMessage = null; - UHTeam recipient = null; - - if(team == null) { - rawMessage = i.t("team.message.format", sender.getDisplayName(), message); - recipient = p.getTeamManager().getTeamForPlayer(sender); - - if(recipient == null) { - sender.sendMessage(i.t("team.message.noTeam")); - return; - } - } - else { - rawMessage = i.t("team.message.formatOtherTeam", sender.getDisplayName(), team.getDisplayName(), message); - recipient = team; - } - - sendRawTeamMessage(sender, rawMessage, recipient); - } - - /** - * Sends a raw team-message from the given player. - * - * @param sender The sender of this message. - * @param rawMessage The raw message to be sent. - * @param team The recipient of this message. - */ - private void sendRawTeamMessage(final Player sender, String rawMessage, UHTeam team) { - - // The message is sent to the players of the team... - for(final Player player : team.getOnlinePlayers()) { - player.sendMessage(rawMessage); - } - - // ... to the spies ... - if(otherTeamChatLocked.containsValue(team)) { - for(UUID playerId : otherTeamChatLocked.keySet()) { - // The message is only sent to the spies not in the team, to avoid double messages - if(otherTeamChatLocked.get(playerId).equals(team) && !team.containsPlayer(playerId)) { - p.getServer().getPlayer(playerId).sendMessage(rawMessage); - } - } - } - - // ... and to the console. - if(p.getConfig().getBoolean("teams-options.teamChat.log")) { - p.getServer().getConsoleSender().sendMessage(rawMessage); - } - - if(!p.getProtipsSender().wasProtipSent(sender, ProTipsSender.PROTIP_LOCK_CHAT)) { - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - p.getProtipsSender().sendProtip(sender, ProTipsSender.PROTIP_LOCK_CHAT); - } - }, 30L); - } - } - - /** - * Sends a global message from the given player. - * - * @param sender The sender of this message. - * @param message The message to be sent. - */ - public void sendGlobalMessage(Player sender, String message) { - // This message will be sent synchronously. - // The players' messages are sent asynchronously. - // That's how we differentiates the messages sent through /g and the messages sent using - // the normal chat. - - sender.chat(message); - } - - - /** - * Toggles the chat between the global chat and the team chat. - * - * @param player The chat of this player will be toggled. - * @return true if the chat is now the team chat; false else. - */ - public boolean toggleChatForPlayer(Player player) { - return toggleChatForPlayer(player, null); - } - - /** - * Toggles the chat between the global chat and the team chat. - * - * @param player The chat of this player will be toggled. - * @param team The team to chat with. If null, the player's team will be used. - * @return true if the chat is now the team chat; false else. - */ - public boolean toggleChatForPlayer(final Player player, UHTeam team) { - - // Permission check - if(team == null && !player.hasPermission("uh.teamchat.self")) { - player.sendMessage(i.t("team.message.notAllowed.self")); - return false; - } - if(team != null && !player.hasPermission("uh.teamchat.others")) { - player.sendMessage(i.t("team.message.notAllowed.others")); - return false; - } - - - // If the team is not null, we will always go to the team chat - // Else, normal toggle - - if(team != null) { - // if the player was in another team chat before, we removes it. - teamChatLocked.remove(player.getUniqueId()); - otherTeamChatLocked.put(player.getUniqueId(), team); - - return true; - } - - else { - if(isAnyTeamChatEnabled(player)) { - teamChatLocked.remove(player.getUniqueId()); - otherTeamChatLocked.remove(player.getUniqueId()); - - return false; - } - else { - teamChatLocked.add(player.getUniqueId()); - - Bukkit.getScheduler().runTaskLater(p, new BukkitRunnable() { - @Override - public void run() { - p.getProtipsSender().sendProtip(player, ProTipsSender.PROTIP_USE_G_COMMAND); - } - }, 10L); - - return true; - } - } - } - - /** - * Returns true if the team chat is enabled for the given player. - * - * @param player The player. - * @param team If non-null, this will check if the given player is spying the current team. - * @return - */ - public boolean isTeamChatEnabled(Player player, UHTeam team) { - if(team == null) { - return teamChatLocked.contains(player.getUniqueId()); - } - else { - UHTeam lockedTeam = this.otherTeamChatLocked.get(player.getUniqueId()); - UHTeam playerTeam = p.getTeamManager().getTeamForPlayer(player); - return (lockedTeam != null && lockedTeam.equals(team)) || (playerTeam != null && playerTeam.equals(team)); - } - } - - /** - * Returns true if the team chat is enabled for the given player. - * - * @param player The player. - * @return - */ - public boolean isTeamChatEnabled(Player player) { - return this.isTeamChatEnabled(player, null); - } - - /** - * Returns true if the given player is in the team chat of another team. - * - * @param player The player. - * @return - */ - public boolean isOtherTeamChatEnabled(Player player) { - return otherTeamChatLocked.containsKey(player.getUniqueId()); - } - - /** - * Returns true if a team chat is enabled for the given player. - * - * @param player The player. - * @return - */ - public boolean isAnyTeamChatEnabled(Player player) { - return (teamChatLocked.contains(player.getUniqueId()) || otherTeamChatLocked.containsKey(player.getUniqueId())); - } - - /** - * Returns the other team viewed by the given player, or null if the player is not in - * the chat of another team. - * - * @param player The player. - * @return - */ - public UHTeam getOtherTeamEnabled(Player player) { - return otherTeamChatLocked.get(player.getUniqueId()); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/teams/TeamColor.java b/src/main/java/me/azenet/UHPlugin/teams/TeamColor.java deleted file mode 100644 index 0d7a9fd..0000000 --- a/src/main/java/me/azenet/UHPlugin/teams/TeamColor.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.teams; - -import org.bukkit.ChatColor; - -/** - * Represents a team color. - * - * Also used to convert a string to a ChatColor object. - */ -public enum TeamColor { - AQUA("Aqua", ChatColor.AQUA), - BLACK("Black", ChatColor.BLACK), - BLUE("Blue", ChatColor.BLUE), - DARK_AQUA("Darkaqua", ChatColor.DARK_AQUA), - DARK_BLUE("Darkblue", ChatColor.DARK_BLUE), - DARK_GRAY("Darkgray", ChatColor.DARK_GRAY), - DARK_GREEN("Darkgreen", ChatColor.DARK_GREEN), - DARK_PURPLE("Darkpurple", ChatColor.DARK_PURPLE), - DARK_RED("Darkred", ChatColor.DARK_RED), - GOLD("Gold", ChatColor.GOLD), - GRAY("Gray", ChatColor.GRAY), - GREEN("Green", ChatColor.GREEN), - LIGHT_PURPLE("Lightpurple", ChatColor.LIGHT_PURPLE), - RED("Red", ChatColor.RED), - WHITE("White", ChatColor.WHITE), - YELLOW("Yellow", ChatColor.YELLOW), - RANDOM("?", null); - - private String name; - private ChatColor color; - - TeamColor(String name, ChatColor color) { - this.name = name; - this.color = color; - } - - public ChatColor toChatColor() { - return this.color; - } - - /** - * Returns a ChatColor object from a string. - * - * @param name The name of the color. - * @return The ChatColor object (null if RANDOM or not found). - */ - public static ChatColor getChatColorByName(String name) { - for(TeamColor color : values()) { - if (color.name.equalsIgnoreCase(name)) return color.color; - } - - return null; - } - - /** - * Case&trim-insensitive version of {@link #valueOf(String)}. - * - * @param name The name to get. - * @return A TeamColor value, or null if no value found. - */ - public static TeamColor fromString(String name) { - if(name.equals("?")) { - return RANDOM; - } - - try { - return valueOf(name.trim().toUpperCase()); - } - catch(IllegalArgumentException e) { - // Maybe a color without underscore - for(TeamColor color : values()) { - if(color.name.equalsIgnoreCase(name)) return color; - } - - return null; - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/teams/TeamManager.java b/src/main/java/me/azenet/UHPlugin/teams/TeamManager.java deleted file mode 100644 index 88a5ee4..0000000 --- a/src/main/java/me/azenet/UHPlugin/teams/TeamManager.java +++ /dev/null @@ -1,503 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.teams; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import me.azenet.UHPlugin.utils.UHUtils; -import org.bukkit.ChatColor; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Random; -import java.util.Set; - -public class TeamManager { - - private UHPlugin p = null; - private I18n i = null; - private HashSet<UHTeam> teams = new HashSet<UHTeam>(); - - private int maxPlayersPerTeam; - - - public TeamManager(UHPlugin plugin) { - this.p = plugin; - this.i = p.getI18n(); - - this.maxPlayersPerTeam = p.getConfig().getInt("teams-options.maxPlayersPerTeam"); - } - - /** - * Is the given team registered? - * - * @param team The team. - * @return {@code true} if the team is registered. - */ - public boolean isTeamRegistered(UHTeam team) { - return teams.contains(team); - } - - /** - * Is the given team registered? - * - * @param name The name of the team. - * @return {@code true} if the team is registered. - */ - public boolean isTeamRegistered(String name) { - return getTeam(name) != null; - } - - - /** - * Adds a team. - * - * @param color The color. - * @param name The name of the team. - * - * @return The new team. - * - * @throws IllegalArgumentException if a team with the same name already exists. - */ - public UHTeam addTeam(TeamColor color, String name) { - if(isTeamRegistered(name)) { - throw new IllegalArgumentException("There is already a team named " + name + " registered!"); - } - - UHTeam team = new UHTeam(name, generateColor(color), p); - teams.add(team); - - return team; - } - - /** - * Adds a team. A name is generated based on the color. - * - * @param color The color. - * - * @return The new team. - * - * @throws IllegalArgumentException if a team with the same name already exists. - */ - public UHTeam addTeam(TeamColor color) { - - color = generateColor(color); - String teamName = color.toString().toLowerCase(); - - if(isTeamRegistered(teamName)) { // Taken! - Random rand = new Random(); - do { - teamName = color.toString().toLowerCase() + rand.nextInt(1000); - } while(isTeamRegistered(teamName)); - } - - UHTeam team = new UHTeam(teamName, color, p); - teams.add(team); - - return team; - } - - /** - * Adds a team from an UHTeam object. - * - * @param team The team. - * @return The new team. - * - * @throws IllegalArgumentException if a team with the same name already exists. - */ - public UHTeam addTeam(UHTeam team) { - if(isTeamRegistered(team)) { - throw new IllegalArgumentException("There is already a team named " + team.getName() + " registered!"); - } - - teams.add(team); - return team; - } - - /** - * Deletes a team. - * - * @param team The team to delete. - * @param dontNotify If true, the player will not be notified about the leave. - * @return boolean True if a team was removed. - */ - public boolean removeTeam(UHTeam team, boolean dontNotify) { - if(team != null) { - if(dontNotify) { - for(OfflinePlayer player : team.getPlayers()) { - this.removePlayerFromTeam(player, true); - } - } - - team.deleteTeam(); - } - - return teams.remove(team); - } - - /** - * Deletes a team. - * - * @param team The team to delete. - * @return boolean True if a team was removed. - */ - public boolean removeTeam(UHTeam team) { - return removeTeam(team, false); - } - - /** - * Deletes a team. - * - * @param name The name of the team to delete. - * @return boolean True if a team was removed. - */ - public boolean removeTeam(String name) { - return removeTeam(getTeam(name), false); - } - - /** - * Deletes a team. - * - * @param name The name of the team to delete. - * @param dontNotify If true, the player will not be notified about the leave. - * @return boolean True if a team was removed. - */ - public boolean removeTeam(String name, boolean dontNotify) { - return removeTeam(getTeam(name), dontNotify); - } - - /** - * Adds a player to a team. - * - * @param teamName The team in which we adds the player. - * @param player The player to add. - * @throws IllegalArgumentException if the team does not exists. - */ - public void addPlayerToTeam(String teamName, OfflinePlayer player) { - UHTeam team = getTeam(teamName); - - if(team == null) { - throw new IllegalArgumentException("There isn't any team named" + teamName + " registered!"); - } - - team.addPlayer(player); - } - - /** - * Removes a player from his team. - * - * @param player The player to remove. - * @param dontNotify If true, the player will not be notified about the leave. - */ - public void removePlayerFromTeam(OfflinePlayer player, boolean dontNotify) { - UHTeam team = getTeamForPlayer(player); - if(team != null) { - team.removePlayer(player, dontNotify); - } - } - - /** - * Removes a player from his team. - * - * @param player The player to remove. - */ - public void removePlayerFromTeam(OfflinePlayer player) { - removePlayerFromTeam(player, false); - } - - - /** - * Removes all teams. - * - * @param dontNotify If true, the player will not be notified when they leave the destroyed team. - */ - public void reset(boolean dontNotify) { - // 1: scoreboard reset - for(UHTeam team : new HashSet<UHTeam>(teams)) { - this.removeTeam(team, dontNotify); - } - - // 2: internal list reset - teams.clear(); - } - - /** - * Removes all teams. - */ - public void reset() { - reset(false); - } - - /** - * Sets the correct display name of a player, according to his team. - * - * @param player - */ - public void colorizePlayer(OfflinePlayer offlinePlayer) { - if(!p.getConfig().getBoolean("colorizeChat")) { - return; - } - - if(!offlinePlayer.isOnline()) { - return; - } - - Player player = (Player) offlinePlayer; - - UHTeam team = getTeamForPlayer(player); - - if(team == null) { - player.setDisplayName(player.getName()); - } - else { - if(team.getColor() != null) { - player.setDisplayName(team.getColor().toChatColor() + player.getName() + ChatColor.RESET); - } - else { - player.setDisplayName(player.getName()); - } - } - } - - /** - * Returns all the teams. - * - * @return The teams. - */ - public Set<UHTeam> getTeams() { - return teams; - } - - /** - * Returns the maximal number of players in each team. - * - * @return The max. - */ - public int getMaxPlayersPerTeam() { - return maxPlayersPerTeam; - } - - /** - * Returns the UHTeam object of the team with the given name. - * - * @param name The name of the team. - * @return The team, or null if the team does not exists. - */ - public UHTeam getTeam(String name) { - for(UHTeam t : teams) { - if (t.getName().equalsIgnoreCase(name)) { - return t; - } - } - - return null; - } - - /** - * Gets a player's team. - * - * @param player The player. - * @return The team of this player. - */ - public UHTeam getTeamForPlayer(OfflinePlayer player) { - for(UHTeam t : teams) { - if (t.containsPlayer(player.getUniqueId())) return t; - } - - return null; - } - - /** - * Checks if two players are in the same team. - * - * @param player1 The first player. - * @param player2 The second player - * @return True if the players are in the same team, false else. - */ - public boolean inSameTeam(Player pl, Player pl2) { - return (getTeamForPlayer(pl).equals(getTeamForPlayer(pl2))); - } - - /** - * Generates a color from the given color. - * <p> - * If the color is neither {@link TeamColor#RANDOM} nor {@code null}, returns the given color.<br /> - * Else, generates a random unused (if possible) color. - * @param color - * @return - */ - public TeamColor generateColor(TeamColor color) { - if(color != null && color != TeamColor.RANDOM) { - return color; - } - - // A list of the currently used colors. - HashSet<TeamColor> availableColors = new HashSet<TeamColor>(Arrays.asList(TeamColor.values())); - availableColors.remove(TeamColor.RANDOM); - for(UHTeam team : getTeams()) { - availableColors.remove(team.getColor()); - } - - if(availableColors.size() != 0) { - return (TeamColor) availableColors.toArray()[(new Random()).nextInt(availableColors.size())]; - } - else { - // length-1 so the RANDOM option is never selected. - return TeamColor.values()[(new Random()).nextInt(TeamColor.values().length - 1)]; - } - } - - /** - * Imports the teams from the configuration. - * - * @return The number of teams imported. - */ - public int importTeamsFromConfig() { - if(p.getConfig().getList("teams") != null) { - int teamsCount = 0; - for(Object teamRaw : p.getConfig().getList("teams")) { - if(teamRaw instanceof String && teamRaw != null) { - String[] teamRawSeparated = ((String) teamRaw).split(","); - TeamColor color = TeamColor.fromString(teamRawSeparated[0]); - if(color == null) { - p.getLogger().warning(i.t("load.invalidTeam", (String) teamRaw)); - } - else { - if(teamRawSeparated.length == 2) { // "color,name" - UHTeam newTeam = addTeam(color, teamRawSeparated[1]); - p.getLogger().info(i.t("load.namedTeamAdded", newTeam.getName(), newTeam.getColor().toString())); - teamsCount++; - } - else if(teamRawSeparated.length == 1) { // "color" - UHTeam newTeam = addTeam(color, teamRawSeparated[0]); - p.getLogger().info(i.t("load.teamAdded", newTeam.getColor().toString())); - teamsCount++; - } - else { - p.getLogger().warning(i.t("load.invalidTeam", (String) teamRaw)); - } - } - } - } - - return teamsCount; - } - - return 0; - } - - /** - * Displays a chat-based GUI (using tellraw formatting) to player to select a team. - * <p> - * Nothing is displayed if the player cannot use the /join command. - * - * @param player The receiver of the chat-GUI. - */ - public void displayTeamChooserChatGUI(Player player) { - if(!player.hasPermission("uh.player.join.self")) return; - - if(p.getGameManager().isGameRunning()) { - if(!p.getGameManager().isGameWithTeams()) { - return; - } - } - - player.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); - - if(p.getTeamManager().getTeams().size() != 0) { - player.sendMessage(i.t("team.gui.choose")); - - boolean displayPlayers = p.getConfig().getBoolean("teams-options.gui.displayPlayersInTeams"); - - for(UHTeam team : p.getTeamManager().getTeams()) { - - String text = "{\"text\":\"\",\"extra\":["; - - // Team count (something like "[2/5]”) - text += "{"; - if(maxPlayersPerTeam != 0) { - text += "\"text\": \"" + i.t("team.gui.playersCount", String.valueOf(team.getSize()), String.valueOf(maxPlayersPerTeam)) + "\", "; - } - else { - text += "\"text\": \"" + i.t("team.gui.playersCountUnlimited", String.valueOf(team.getSize())) + "\", "; - } - - String players = ""; - if(displayPlayers) { - String bullet = "\n - "; - for(OfflinePlayer opl : team.getPlayers()) { - if(!p.getGameManager().isGameRunning()) { - players += bullet + i.t("team.list.itemPlayer", opl.getName()); - } - else { - if(p.getGameManager().isPlayerDead(opl.getUniqueId())) { - players += bullet + i.t("team.list.itemPlayerDead", opl.getName()); - } - else { - players += bullet + i.t("team.list.itemPlayerAlive", opl.getName()); - } - } - } - } - text += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("team.gui.tooltipCount", String.valueOf(team.getPlayers().size())) + players + "\"}"; - text += "},"; - - text += "{\"text\":\" \"},{"; - - // Team name (click event is here) - text += "\"text\":\"" + team.getName() + "\","; - text += "\"color\":\"" + team.getColor().toString().toLowerCase() + "\","; - text += "\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/join " + team.getName() + "\"},"; - if(team.containsPlayer(player)) { - text += "\"bold\":\"true\","; - text += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("team.gui.tooltipJoinInside", team.getDisplayName()) + "\"}"; - } - else { - text += "\"hoverEvent\":{\"action\":\"show_text\",\"value\":\"" + i.t("team.gui.tooltipJoin", team.getDisplayName()) + "\"}"; - } - text += "}"; - - text += "]}"; - - UHUtils.sendJSONMessage(player, text); - } - - if(p.getTeamManager().getTeamForPlayer(player) != null && player.hasPermission("uh.player.leave.self")) { - String text = "{"; - text += "\"text\":\"" + i.t("team.gui.leaveTeam") + "\","; - text += "\"clickEvent\":{\"action\":\"run_command\",\"value\":\"/leave\"}"; - text += "}"; - - UHUtils.sendJSONMessage(player, text); - } - else { - player.sendMessage(i.t("team.gui.howToDisplayAgain")); - } - } - else { - // No teams. - player.sendMessage(i.t("team.gui.noTeams")); - } - - player.sendMessage(ChatColor.GRAY + "⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅"); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/teams/UHTeam.java b/src/main/java/me/azenet/UHPlugin/teams/UHTeam.java deleted file mode 100644 index 2ce7581..0000000 --- a/src/main/java/me/azenet/UHPlugin/teams/UHTeam.java +++ /dev/null @@ -1,378 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.teams; - -import me.azenet.UHPlugin.UHPlugin; -import me.azenet.UHPlugin.i18n.I18n; -import org.apache.commons.lang.Validate; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; -import org.bukkit.scoreboard.Scoreboard; -import org.bukkit.scoreboard.Team; - -import java.util.HashSet; -import java.util.Random; -import java.util.Set; -import java.util.UUID; - -public class UHTeam { - private UHPlugin plugin = null; - private I18n i = null; - - private String name = null; - private String internalName = null; - private String displayName = null; - private TeamColor color = null; - - private HashSet<UUID> players = new HashSet<UUID>(); - - - public UHTeam(String name, TeamColor color, UHPlugin plugin) { - Validate.notNull(name, "The name cannot be null."); - Validate.notNull(plugin, "The plugin cannot be null."); - - this.plugin = plugin; - this.i = plugin.getI18n(); - - this.name = name; - - // We don't use generateColor directly because we want to keep the "null" color. - if(color == TeamColor.RANDOM) this.color = plugin.getTeamManager().generateColor(color); - else this.color = color; - - - // We use a random internal name because the name of a team, in Minecraft vanilla, is limited - // (16 characters max). - Random rand = new Random(); - this.internalName = String.valueOf(rand.nextInt(99999999)) + String.valueOf(rand.nextInt(99999999)); - - if(this.color != null) { - this.displayName = this.color.toChatColor() + name + ChatColor.RESET; - } - else { - this.displayName = name; - } - - Scoreboard sb = this.plugin.getScoreboardManager().getScoreboard(); - - sb.registerNewTeam(this.internalName); - Team t = sb.getTeam(this.internalName); - - if(this.color != null) { - t.setPrefix(this.color.toChatColor().toString()); - t.setSuffix(ChatColor.RESET.toString()); - } - - t.setCanSeeFriendlyInvisibles(plugin.getConfig().getBoolean("teams-options.canSeeFriendlyInvisibles", true)); - t.setAllowFriendlyFire(plugin.getConfig().getBoolean("teams-options.allowFriendlyFire", true)); - } - - /** - * Returns the name of the team. - * - * Can include spaces. - * - * @return The name. - */ - public String getName() { - return name; - } - - /** - * Returns the display name of the team. - * - * This name is: - * - if the team is uncolored, the name of the team; - * - else, the name of the team with: - * - before, the color of the team; - * - after, the "reset" formatting mark (§r). - * - * @return The display name. - */ - public String getDisplayName() { - return displayName; - } - - /** - * Returns the players inside this team. - * - * @return The players. - */ - public Set<OfflinePlayer> getPlayers() { - HashSet<OfflinePlayer> playersList = new HashSet<OfflinePlayer>(); - - for(UUID id : players) { - Player player = plugin.getServer().getPlayer(id); - if(player != null) { - playersList.add(player); - } - else { - playersList.add(plugin.getServer().getOfflinePlayer(id)); - } - } - - return playersList; - } - - /** - * Returns the online players inside this team. - * - * @return The online players. - */ - public Set<Player> getOnlinePlayers() { - HashSet<Player> playersList = new HashSet<Player>(); - - for(UUID id : players) { - Player player = plugin.getServer().getPlayer(id); - if(player != null && player.isOnline()) { - playersList.add(player); - } - } - - return playersList; - } - - /** - * Returns the UUIDs of the players inside this team. - * - * @return The UUIDs of the players. - */ - @SuppressWarnings("unchecked") - public Set<UUID> getPlayersUUID() { - return (HashSet<UUID>) players.clone(); - } - - /** - * Returns the UUIDs of the online players inside this team. - * - * @return The UUID of the online players. - */ - public Set<UUID> getOnlinePlayersUUID() { - HashSet<UUID> playersList = new HashSet<UUID>(); - - for(UUID id : players) { - Player player = plugin.getServer().getPlayer(id); - if(player != null) { - playersList.add(id); - } - } - - return playersList; - } - - /** - * Returns the size of this team. - * - * @return The size. - */ - public int getSize() { - return players.size(); - } - - /** - * Returns true if the team is empty. - * - * @return The emptiness. - */ - public boolean isEmpty() { - return getSize() == 0; - } - - /** - * Adds a player inside this team. - * - * @param player The player to add. - */ - public void addPlayer(OfflinePlayer player) { - addPlayer(player, false); - } - - /** - * Adds a player inside this team. - * - * @param player The player to add. - * @param silent If true, the player will not be notified about this. - */ - public void addPlayer(OfflinePlayer player, boolean silent) { - Validate.notNull(player, "The player cannot be null."); - - if(plugin.getTeamManager().getMaxPlayersPerTeam() != 0 - && this.players.size() >= plugin.getTeamManager().getMaxPlayersPerTeam()) { - - throw new RuntimeException("The team " + getName() + " is full"); - } - - plugin.getTeamManager().removePlayerFromTeam(player, true); - - players.add(player.getUniqueId()); - plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).addPlayer(player); - - plugin.getTeamManager().colorizePlayer(player); - - if(!silent && player.isOnline()) { - ((Player) player).sendMessage(i.t("team.addplayer.added", getDisplayName())); - } - } - - /** - * Removes a player from this team. - * - * Nothing is done if the player wasn't in this team. - * - * @param player The player to remove. - */ - public void removePlayer(OfflinePlayer player) { - removePlayer(player, false); - } - - /** - * Removes a player from this team. - * - * Nothing is done if the player wasn't in this team. - * - * @param player The player to remove. - * @param silent If true, the player will not be notified. - */ - public void removePlayer(OfflinePlayer player, boolean silent) { - Validate.notNull(player, "The player cannot be null."); - - players.remove(player.getUniqueId()); - unregisterPlayer(player); - - if(!silent && player.isOnline()) { - ((Player) player).sendMessage(i.t("team.removeplayer.removed", getDisplayName())); - } - } - - /** - * Unregisters a player from the scoreboard and uncolorizes the pseudo. - * - * Internal use, avoids a ConcurrentModificationException in this.deleteTeam() - * (this.players is listed and emptied simultaneously, else). - * - * @param player - */ - private void unregisterPlayer(OfflinePlayer player) { - if(player == null) return; - - plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).removePlayer(player); - plugin.getTeamManager().colorizePlayer(player); - } - - /** - * Deletes this team. - * - * The players inside the team are left without any team. - */ - public void deleteTeam() { - // We removes the players from the team (scoreboard team too) - for(UUID id : players) { - OfflinePlayer player = plugin.getServer().getOfflinePlayer(id); - - if(player != null && player.isOnline()) { - ((Player) player).sendMessage(plugin.getI18n().t("team.removeplayer.removed", getDisplayName())); - } - - unregisterPlayer(player); - } - - this.players.clear(); - - // Then the scoreboard team is deleted. - plugin.getScoreboardManager().getScoreboard().getTeam(this.internalName).unregister(); - - } - - /** - * Returns true if the given player is in this team. - * - * @param player The player to check. - * @return true if the given player is in this team. - */ - public boolean containsPlayer(Player player) { - Validate.notNull(player, "The player cannot be null."); - - return players.contains(player.getUniqueId()); - } - - /** - * Returns true if the player with the given UUID is in this team. - * - * @param id The UUID of the player to check. - * @return true if the given player is in this team. - */ - public boolean containsPlayer(UUID id) { - Validate.notNull(id, "The player cannot be null."); - - return players.contains(id); - } - - /** - * Teleports the entire team to the given location. - * - * @param lo - */ - public void teleportTo(Location lo) { - Validate.notNull(lo, "The location cannot be null."); - - for (UUID id : players) { - Player player = plugin.getServer().getPlayer(id); - if(player != null && player.isOnline()) { - player.teleport(lo, TeleportCause.PLUGIN); - } - } - } - - /** - * Returns the color of the team. - * - * @return - */ - public TeamColor getColor() { - return color; - } - - - - @Override - public int hashCode() { - return ((name == null) ? 0 : name.hashCode()); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof UHTeam)) - return false; - UHTeam other = (UHTeam) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/timers/TimerManager.java b/src/main/java/me/azenet/UHPlugin/timers/TimerManager.java deleted file mode 100644 index df86584..0000000 --- a/src/main/java/me/azenet/UHPlugin/timers/TimerManager.java +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.timers; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -public class TimerManager { - - private Map<String,UHTimer> timers = new HashMap<String,UHTimer>(); - private UHTimer mainTimer = null; - - /** - * Cached list of the running timers - */ - private Map<String,UHTimer> runningTimers = new HashMap<String,UHTimer>(); - - /** - * List of the timers to resume if running timers are paused. - * - * @see {@link #pauseAllRunning(boolean)}. - */ - private HashSet<UHTimer> timersToResume = new HashSet<UHTimer>(); - - - public TimerManager() { - - } - - /** - * Registers the main timer, used to display the episodes countdown. - * - * @param timer The timer. - */ - public void registerMainTimer(UHTimer timer) { - this.mainTimer = timer; - timer.setRegistered(true); - } - - /** - * Returns the main timer, used to display the episodes countdown. - * - * @return The main timer. - */ - public UHTimer getMainTimer() { - return this.mainTimer; - } - - /** - * Registers a timer. - * - * @param timer The timer to register. - * @throws IllegalArgumentException if a timer with the same name is already registered. - */ - public void registerTimer(UHTimer timer) { - - if(timers.get(timer.getName()) != null) { - throw new IllegalArgumentException("A timer with the name " + timer.getName() + " is already registered."); - } - - timers.put(timer.getName(), timer); - - timer.setRegistered(true); - } - - /** - * Unregisters a timer. - * <p> - * If the timer was not registered, nothing is done. - * - * @param timer The timer to unregister. - */ - public void unregisterTimer(UHTimer timer) { - timers.remove(timer.getName()); - runningTimers.remove(timer.getName()); - - timer.setRegistered(false); - } - - /** - * Updates the internal list of started timers. - */ - public void updateStartedTimersList() { - runningTimers = new HashMap<String,UHTimer>(); - - if(getMainTimer() != null && getMainTimer().isRunning()) { - runningTimers.put(getMainTimer().getName(), getMainTimer()); - } - - for(UHTimer timer : timers.values()) { - if(timer.isRunning()) { - runningTimers.put(timer.getName(), timer); - } - } - } - - /** - * Returns a timer by his name. - * - * @param name The name of the timer. - * - * @return The timer, or null if there isn't any timer with this name. - */ - public UHTimer getTimer(String name) { - return timers.get(name); - } - - /** - * Returns a collection containing the registered timers. - * - * @return The collection. - */ - public Collection<UHTimer> getTimers() { - return timers.values(); - } - - /** - * Returns a collection containing the running timers. - * - * @return The collection. - */ - public Collection<UHTimer> getRunningTimers() { - return runningTimers.values(); - } - - /** - * Pauses (or resumes) all the running timers. - * - * @param paused If true, all the timers will be paused. Else, resumed. - */ - public void pauseAll(boolean paused) { - for(UHTimer timer : getRunningTimers()) { - timer.setPaused(paused); - } - - if(!paused) { - // If we restart all the timers regardless to their previous state, - // this data is meaningless. - timersToResume.clear(); - } - } - - /** - * Pauses (or resumes) all the running timers. - * <p> - * This method will only resume the previously-running timers. - * - * @param paused If true, all the timers will be paused. Else, resumed. - */ - public void pauseAllRunning(boolean paused) { - if(paused) { - for(UHTimer timer : getRunningTimers()) { - if(!timer.isPaused()) { - timer.setPaused(true); - timersToResume.add(timer); - } - } - } - else { - for(UHTimer timer : timersToResume) { - timer.setPaused(false); - } - - timersToResume.clear(); - } - } -} diff --git a/src/main/java/me/azenet/UHPlugin/timers/UHTimer.java b/src/main/java/me/azenet/UHPlugin/timers/UHTimer.java deleted file mode 100644 index 31ff1ec..0000000 --- a/src/main/java/me/azenet/UHPlugin/timers/UHTimer.java +++ /dev/null @@ -1,345 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.timers; - -import me.azenet.UHPlugin.events.TimerEndsEvent; -import me.azenet.UHPlugin.events.TimerStartsEvent; -import org.apache.commons.lang.Validate; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; - -import java.util.UUID; - - -/** - * Represents a timer. - * - * @author Amaury Carrade - */ -public class UHTimer { - - private UUID id = null; - private String name = null; - private Boolean registered = false; - private Boolean running = false; - - private Long startTime = 0l; - private Integer duration = 0; // seconds - - // Cached values - private Integer hoursLeft = 0; - private Integer minutesLeft = 0; - private Integer secondsLeft = 0; - - // Old values, used by the scoreboard to reset the scores. - private Integer oldHoursLeft = -1; - private Integer oldMinutesLeft = -1; - private Integer oldSecondsLeft = -1; - - // Pause - private Boolean paused = false; - private Long pauseTime = 0l; - - // Display this timer following the format "hh:mm:ss"? - private Boolean displayHoursInTimer = false; - - - public UHTimer(String name) { - Validate.notNull(name, "The name cannot be null"); - - this.id = UUID.randomUUID(); // only used as a hashCode. - this.name = name; - } - - /** - * Sets the duration of the timer, in seconds. - * - * @param seconds The duration. - */ - public void setDuration(int seconds) { - this.duration = seconds; - - this.hoursLeft = (int) Math.floor(this.duration / 3600); - this.minutesLeft = (int) (Math.floor(this.duration / 60) - (this.hoursLeft * 60)); - this.secondsLeft = this.duration - (this.minutesLeft * 60 + this.hoursLeft * 3600); - - // Lower than 100 because else the counter text is longer than 16 characters. - this.displayHoursInTimer = (this.hoursLeft != 0 && this.hoursLeft < 100); - } - - /** - * Starts this timer. - * - * If this is called while the timer is running, the timer is restarted. - */ - public void start() { - this.running = true; - this.startTime = System.currentTimeMillis(); - - Bukkit.getServer().getPluginManager().callEvent(new TimerStartsEvent(this)); - } - - /** - * Stops this timer. - */ - public void stop() { - stop(false); - } - - /** - * Stops this timer. - * - * @param ended If true, the timer was stopped because the timer was up. - */ - private void stop(boolean wasUp) { - TimerEndsEvent event = new TimerEndsEvent(this, wasUp); - Bukkit.getServer().getPluginManager().callEvent(event); - - if(isRegistered()) { - if(event.getRestart()) { - start(); - } - else { - this.running = false; - this.startTime = 0l; - - this.hoursLeft = 0; - this.minutesLeft = 0; - this.secondsLeft = 0; - - this.oldHoursLeft = 0; - this.oldMinutesLeft = 0; - this.oldSecondsLeft = 0; - } - } - } - - /** - * Updates the timer. - */ - public void update() { - if(running && !paused) { - oldHoursLeft = hoursLeft; - oldMinutesLeft = minutesLeft; - oldSecondsLeft = secondsLeft; - - long timeSinceStart = System.currentTimeMillis() - this.startTime; // ms - - if(timeSinceStart >= getDuration() * 1000) { - stop(true); - } - else { - Integer countSecondsLeft = (int) (getDuration() - Math.floor(timeSinceStart / 1000)); - - secondsLeft = countSecondsLeft % 60; - minutesLeft = (countSecondsLeft % 3600) / 60; - hoursLeft = (int) Math.floor(countSecondsLeft / 3600); - } - } - } - - /** - * Pauses (or restarts after a pause) the timer. - * <p> - * If the timer is not running, nothing is done. - * - * @param pause If true the timer will be paused. - */ - public void setPaused(boolean pause) { - if(this.running) { - // The pause is only set once (as example if the user executes /uh freeze all twice). - if(pause && !this.paused) { - this.paused = true; - this.pauseTime = System.currentTimeMillis(); - } - - if(!pause && this.paused) { - // We have to add to the time of the start of the episode the elapsed time - // during the pause. - this.startTime += (System.currentTimeMillis() - this.pauseTime); - this.pauseTime = 0l; - - this.paused = false; - } - } - } - - /** - * Checks if the timer is registered in the TimerManager. - * - * @return true if the timer is registered. - */ - public Boolean isRegistered() { - return registered; - } - - /** - * Marks a timer as registered, or not. - * - * @param registered true if the timer is now registered. - */ - protected void setRegistered(Boolean registered) { - this.registered = registered; - } - - /** - * Returns the name of the timer. - * - * @return The name. - */ - public String getName() { - return name; - } - - /** - * Returns the display name of the timer. - * <p> - * The display name is the name with all &-based color codes replaced by §-based ones. - * - * @return The name. - */ - public String getDisplayName() { - return ChatColor.translateAlternateColorCodes('&', name); - } - - - /** - * Checks if the timer is currently running. - * - * @return true if the timer is running. - */ - public Boolean isRunning() { - return running; - } - - /** - * Returns the duration of the timer, in seconds. - * - * @return The duration. - */ - public Integer getDuration() { - return duration; - } - - /** - * Returns the number of hours left until the end of this countdown. - * - * @return The number of hours left. - */ - public Integer getHoursLeft() { - return hoursLeft; - } - - /** - * Returns the number of minutes left until the end of this countdown. - * - * @return The number of minutes left. - */ - public Integer getMinutesLeft() { - return minutesLeft; - } - - /** - * Returns the number of seconds left until the end of this countdown. - * - * @return The number of seconds left. - */ - public Integer getSecondsLeft() { - return secondsLeft; - } - - /** - * Returns the number of hours left until the end of this countdown, before the last update. - * <p> - * Used by the scoreboard, to remove the old score. - * - * @return The old number of hours left, or -1 if the timer was never updated. - */ - public Integer getOldHoursLeft() { - return oldHoursLeft; - } - - /** - * Returns the number of minutes left until the end of this countdown, before the last update. - * <p> - * Used by the scoreboard, to remove the old score. - * - * @return The old number of minutes left, or -1 if the timer was never updated. - */ - public Integer getOldMinutesLeft() { - return oldMinutesLeft; - } - - /** - * Returns the number of seconds left until the end of this countdown, before the last update. - * <p> - * Used by the scoreboard, to remove the old score. - * - * @return The old number of seconds left, or -1 if the timer was never updated. - */ - public Integer getOldSecondsLeft() { - return oldSecondsLeft; - } - - /** - * Checks if this timer is paused. - * - * @return true if the timer is paused. - */ - public Boolean isPaused() { - return paused; - } - - /** - * Returns true if this timer is displayed as "hh:mm:ss" in the scoreboard. - * - * @return true if this timer is displayed as "hh:mm:ss" in the scoreboard. - */ - public Boolean getDisplayHoursInTimer() { - return displayHoursInTimer; - } - - @Override - public boolean equals(Object other) { - if(!(other instanceof UHTimer)) { - return false; - } - - return ((UHTimer) other).getName().equals(this.getName()); - } - - @Override - public String toString() { - return "UHTimer [" - + (name != null ? "name=" + name + ", " : "") - + (registered != null ? "registered=" + registered + ", " : "") - + (isRunning() ? "running, " : "") - + (startTime != null ? "startTime=" + startTime + ", " : "") - + (duration != null ? "duration=" + duration + ", " : "") - + (isRunning() ? "currentTime=" + getHoursLeft() + "h" + getMinutesLeft() + "m" + getSecondsLeft() + "s" : "") - + (isRunning() && paused != null ? "paused=" + paused + ", " : "") - + (isRunning() && paused && pauseTime != null ? "pauseTime=" + pauseTime : "") + "]"; - } - - @Override - public int hashCode() { - return id.hashCode(); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/utils/CommandUtils.java b/src/main/java/me/azenet/UHPlugin/utils/CommandUtils.java deleted file mode 100644 index 072e671..0000000 --- a/src/main/java/me/azenet/UHPlugin/utils/CommandUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ -package me.azenet.UHPlugin.utils; - -import java.util.Arrays; - - -public class CommandUtils { - - /** - * Returns the args without the first item. - * - * @param args The arguments sent to the parent command. - * @return The arguments to send to the child command. - */ - public static String[] getSubcommandArguments(String[] args) { - if(args.length <= 1) { - return new String[0]; - } - - return Arrays.copyOfRange(args, 1, args.length); - } -} diff --git a/src/main/java/me/azenet/UHPlugin/utils/UHSound.java b/src/main/java/me/azenet/UHPlugin/utils/UHSound.java deleted file mode 100644 index 0c03ded..0000000 --- a/src/main/java/me/azenet/UHPlugin/utils/UHSound.java +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.utils; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Sound; -import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.Player; - -/** - * Represents a sound, with volume and pitch. - * - * @author Amaury Carrade - */ -public class UHSound { - - private Sound sound = null; - private Float volume = 1f; - private Float pitch = 1f; - - /** - * Constructs a sound with volume = 1f and pitch = 1f. - * - * @param sound The sound. - */ - public UHSound(Sound sound) { - this.sound = sound; - } - - public UHSound(Sound sound, Float volume, Float pitch) { - this.sound = sound; - this.volume = volume; - this.pitch = pitch; - } - - /** - * Constructs a sound from a configuration section. - * <p> - * Format: - * <pre> - * key: - * name: string parsable as a sound. If not parsable, null used (i.e. no sound played). - * volume: decimal number - * pitch: decimal number - * </pre> - * - * @param config The configuration section. - */ - public UHSound(ConfigurationSection config) { - if(config == null) { - return; - } - - this.sound = string2Sound(config.getString("name")); - this.volume = (float) config.getDouble("volume"); - this.pitch = (float) config.getDouble("pitch"); - } - - /** - * Plays the sound for the specified player. - * <p> - * The sound is played at the current location of the player. - * <p> - * If the sound is null, fails silently. - * - * @param player The player. - */ - public void play(Player player) { - play(player, player.getLocation()); - } - - /** - * Plays the sound for the specified player, at the specified location. - * <p> - * If the sound is null, fails silently. - * - * @param player The player. - * @param location The location of the sound. - */ - public void play(Player player, Location location) { - player.playSound(location, sound, volume, pitch); - } - - /** - * Plays this sound for all players, at the current location of the players. - */ - public void broadcast() { - for(Player player : Bukkit.getServer().getOnlinePlayers()) { - play(player); - } - } - - public Sound getSound() { - return sound; - } - - public void setSound(Sound sound) { - this.sound = sound; - } - - public Float getVolume() { - return volume; - } - - public void setVolume(Float volume) { - this.volume = volume; - } - - public Float getPitch() { - return pitch; - } - - public void setPitch(Float pitch) { - this.pitch = pitch; - } - - @Override - public String toString() { - return "UHSound [sound=" + sound + ", volume=" + volume + ", pitch=" + pitch + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((pitch == null) ? 0 : pitch.hashCode()); - result = prime * result + ((sound == null) ? 0 : sound.hashCode()); - result = prime * result + ((volume == null) ? 0 : volume.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof UHSound)) { - return false; - } - UHSound other = (UHSound) obj; - if (pitch == null) { - if (other.pitch != null) { - return false; - } - } else if (!pitch.equals(other.pitch)) { - return false; - } - if (sound != other.sound) { - return false; - } - if (volume == null) { - if (other.volume != null) { - return false; - } - } else if (!volume.equals(other.volume)) { - return false; - } - return true; - } - - - /** - * Converts a string to a Sound. - * <p> - * "<code>ANVIL_LAND</code>", "<code>Anvil Land</code>" and "<code>ANVIL Land</code>" are recognized as - * <code>Sound.ANVIL_LAND</code>, as example. - * - * @param soundName The text to be converted. - * @return The corresponding Sound, or null if there isn't any match. - */ - public static Sound string2Sound(String soundName) { - if(soundName != null) { - soundName = soundName.trim().toUpperCase().replace(" ", "_"); - try { - return Sound.valueOf(soundName); - } catch(IllegalArgumentException e) { - // Non-existent sound - return null; - } - } - - return null; - } -} diff --git a/src/main/java/me/azenet/UHPlugin/utils/UHUtils.java b/src/main/java/me/azenet/UHPlugin/utils/UHUtils.java deleted file mode 100644 index 63e9204..0000000 --- a/src/main/java/me/azenet/UHPlugin/utils/UHUtils.java +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Plugin UltraHardcore Reloaded (UHPlugin) - * Copyright (C) 2013 azenet - * Copyright (C) 2014-2015 Amaury Carrade - * - * 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 [http://www.gnu.org/licenses/]. - */ - -package me.azenet.UHPlugin.utils; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import org.bukkit.*; -import org.bukkit.FireworkEffect.Builder; -import org.bukkit.block.Block; -import org.bukkit.command.CommandException; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Firework; -import org.bukkit.entity.Player; -import org.bukkit.inventory.meta.FireworkMeta; - -import java.lang.reflect.InvocationTargetException; -import java.util.Random; - -public class UHUtils { - - /** - * Extracts a string from a list of arguments, starting at the given index. - * - * @param args The raw arguments. - * @param startIndex The index of the first item in the returned string (first argument given: 0). - * - * @return The extracted string. - * - * @throws IllegalArgumentException if the index of the first element is out of the bounds of the arguments' list. - */ - public static String getStringFromCommandArguments(String[] args, int startIndex) { - if(args.length < startIndex) { - throw new IllegalArgumentException("The index of the first element is out of the bounds of the arguments' list."); - } - - String text = ""; - - for(int index = startIndex; index < args.length; index++) { - if(index < args.length - 1) { - text += args[index] + " "; - } - else { - text += args[index]; - } - } - - return text; - } - - /** - * Converts a string to a number of seconds. - * <p> - * Format: - * <ul> - * <li><tt>mm</tt> – number of minutes;</li> - * <li><tt>mm:ss</tt> – minutes and seconds;</li> - * <li><tt>hh:mm:ss</tt> – hours, minutes and seconds.</li> - * </ul> - * - * - * @param text The text to be converted. - * @return The number of seconds represented by this string. - * - * @throws IllegalArgumentException if the text is not formatted as above. - * @throws NumberFormatException if the text between the colons cannot be converted in integers. - */ - public static int string2Time(String text) { - String[] splitted = text.split(":"); - - if(splitted.length > 3) { - throw new IllegalArgumentException("Badely formatted string in string2time, formats allowed are mm, mm:ss or hh:mm:ss."); - } - - if(splitted.length == 1) { // "mm" - return Integer.valueOf(splitted[0]) * 60; - } - else if(splitted.length == 2) { // "mm:ss" - return Integer.valueOf(splitted[0]) * 60 + Integer.valueOf(splitted[1]); - } - else { // "hh:mm:ss" - return Integer.valueOf(splitted[0]) * 3600 + Integer.valueOf(splitted[1]) * 60 + Integer.valueOf(splitted[2]); - } - } - - /** - * Sends a JSON-formatted message to player. - * <p> - * If ProtocolLib is not available, fallback to the tellraw command. - * - * @param player The receiver of the message. - * @param json The message. - * @return true if the message was sent. - */ - public static boolean sendJSONMessage(Player player, String json) { - try { - PacketContainer message = new PacketContainer(PacketType.Play.Server.CHAT); - message.getChatComponents().write(0, WrappedChatComponent.fromJson(json)); - - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, message); - return true; - } catch (InvocationTargetException e) { - e.printStackTrace(); - return false; - } - - } catch (NoClassDefFoundError e) { - // Fallback to the tellraw command - try { - return Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), - "tellraw " + player.getName() + " " + json); - - } catch(CommandException cmde) { - return false; - } - } - } - - - /** - * Finds a safe spot where teleport the player, and teleport the player to that spot. - * If a spot is not found, the player is not teleported, except if {@code force} is set to true. - * - * @param player - * @param location - * @param force If true the player will be teleported to the exact given location if there is no safe spot. - * @return true if the player was effectively teleported. - */ - public static boolean safeTP(Player player, Location location, boolean force) { - // If the target is safe, let's go - if(isSafeSpot(location)) { - player.teleport(location); - return true; - } - - // If the teleportation is forced, let's go - if(force) { - player.teleport(location); - return true; - } - - Location safeSpot = searchSafeSpot(location); - - // A spot was found, let's teleport. - if(safeSpot != null) { - player.teleport(safeSpot); - return true; - } - // No spot found; the teleportation is cancelled. - else { - return false; - } - } - - /** - * Searches a safe spot where teleport the player, and teleport the player to that spot. - * If a spot is not found, the player is not teleported, except if {@code force} is set to true. - * - * @param player - * @param location - * @return true if the player was effectively teleported. - */ - public static boolean safeTP(Player player, Location location) { - return safeTP(player, location, false); - } - - /** - * Searches a safe spot in the given location. - * - * The spot is in the same X;Z coordinates. - * - * @param location The location where to find a safe spot. - * @return A Location object representing the safe spot, or null if no safe spot is available. - */ - public static Location searchSafeSpot(Location location) { - // We try to find a spot above or below the target - - Location safeSpot = null; - final int maxHeight = (location.getWorld().getEnvironment() == World.Environment.NETHER) ? 125 : location.getWorld().getMaxHeight() - 2; // (thx to WorldBorder) - - for(int yGrow = (int) location.getBlockY(), yDecr = (int) location.getBlockY(); yDecr >= 1 || yGrow <= maxHeight; yDecr--, yGrow++) { - // Above? - if(yGrow < maxHeight) { - Location spot = new Location(location.getWorld(), location.getBlockX(), yGrow, location.getBlockZ()); - if(isSafeSpot(spot)) { - safeSpot = spot; - break; - } - } - - // Below? - if(yDecr > 1 && yDecr != yGrow) { - Location spot = new Location(location.getWorld(), location.getX(), yDecr, location.getZ()); - if(isSafeSpot(spot)) { - safeSpot = spot; - break; - } - } - } - - // A spot was found, we changes the pitch & yaw according to the original location. - if(safeSpot != null) { - safeSpot.setPitch(location.getPitch()); - safeSpot.setYaw(location.getYaw()); - } - - return safeSpot; - } - - /** - * Checks if a given location is safe. - * A safe location is a location with two breathable blocks (aka transparent block or water) - * over something solid (or water). - * - * @param location - * @return true if the location is safe. - */ - public static boolean isSafeSpot(Location location) { - Block blockCenter = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - Block blockAbove = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() + 1, location.getBlockZ()); - Block blockBelow = location.getWorld().getBlockAt(location.getBlockX(), location.getBlockY() - 1, location.getBlockZ()); - - if((blockCenter.getType().isTransparent() || (blockCenter.isLiquid() && !blockCenter.getType().equals(Material.LAVA) && !blockCenter.getType().equals(Material.STATIONARY_LAVA))) - && (blockAbove.getType().isTransparent() || (blockAbove.isLiquid() && !blockAbove.getType().equals(Material.LAVA) && !blockCenter.getType().equals(Material.STATIONARY_LAVA)))) { - // two breathable blocks: ok - - if(blockBelow.getType().isSolid() || blockBelow.getType().equals(Material.WATER) || blockBelow.getType().equals(Material.STATIONARY_WATER)) { - // The block below is solid, or liquid (but not lava) - return true; - } - else { - return false; - } - } - else { - return false; - } - } - - - /** - * Spawns a random firework at the given location. - * - * Please note: because the power of a firework is an integer, the min/max heights - * are with a precision of ±5 blocks. - * - * @param location The location where the firework will be spawned. - * @param heightMin The minimal height of the explosion. - * @param heightMax The maximal height of the explosion. - * - * @return The random firework generated. - */ - public static Firework generateRandomFirework(Location location, int heightMin, int heightMax) { - Random rand = new Random(); - - Firework firework = (Firework) location.getWorld().spawnEntity(location, EntityType.FIREWORK); - FireworkMeta meta = firework.getFireworkMeta(); - - int effectsCount = rand.nextInt(3) + 1; - - for(int i = 0; i < effectsCount; i++) { - meta.addEffect(generateRandomFireworkEffect()); - } - - // One level of power is half a second of flight time. - // In half a second, a firework fly ~5 blocks. - // So, one level of power = ~5 blocks. - meta.setPower((int) Math.min(Math.floor((heightMin / 5) + rand.nextInt(heightMax / 5)), 128D)); - - firework.setFireworkMeta(meta); - - return firework; - } - - /** - * Generates a random firework effect. - * - * @return The firework effect. - */ - private static FireworkEffect generateRandomFireworkEffect() { - Random rand = new Random(); - Builder fireworkBuilder = FireworkEffect.builder(); - - int colorCount = rand.nextInt(3) + 1; - int trailCount = rand.nextInt(3) + 1; - - fireworkBuilder.flicker(rand.nextInt(3) == 1); - fireworkBuilder.trail(rand.nextInt(3) == 1); - - for(int i = 0; i < colorCount; i++) { - fireworkBuilder.withColor(generateRandomColor()); - } - - for(int i = 0; i < trailCount; i++) { - fireworkBuilder.withFade(generateRandomColor()); - } - - // Random shape - FireworkEffect.Type[] types = FireworkEffect.Type.values(); - fireworkBuilder.with(types[rand.nextInt(types.length)]); - - return fireworkBuilder.build(); - } - - /** - * Generates a random color. - * - * @return The color. - */ - private static Color generateRandomColor() { - Random rand = new Random(); - return Color.fromBGR(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)); - } -} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 7c538a5..8db78d1 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -11,7 +11,7 @@ # Warning: NEVER USE TABS in this file, always spaces, to indent. -# Available languages: en_US, fr_FR, pt_PT, pt_BR, cs_CZ. +# Available languages: en_US, fr_FR, pt_PT, pt_BR, cs_CZ, zh_CN. # Empty value: system language. lang: @@ -29,6 +29,9 @@ episodes: # Don't remove the "quotes" (because of the commas)! length: "20:00" + # A title is displayed when the episode changes. + title: true + map: @@ -46,7 +49,49 @@ map: # The replaceSolid one, where there was an other kind of block. replaceAir: GLASS replaceSolid: BEDROCK + border: + # The world border manager. Can be: + # - "vanilla", to use the vanilla world border; or + # - "brettflan", to use the WorldBorder Bukkit plugin by Brettflan + # (http://dev.bukkit.org/bukkit-plugins/worldborder/). + # + # If the shape is "circular", fallbacks to "brettflan" as the vanilla world border don't + # support circular borders. And if the WorldBorder plugin is not installed, fallbacks to + # no border. + motor: "vanilla" + + # The amount of blocks a player may safely be outside the border before taking damage. + # Only for the vanilla world border. Ignored else. + damagesBuffer: 5 + + # The amount of damage a player takes when outside the border plus the border buffer. + # The damages delt is calculated by multiplying this amount by the number of blocks behind the buffer. + # Only for the vanilla world border. Ignored else. + damagesAmount: 0.2 + + # The warning distance that causes the screen to be tinted red when the player is within the specified + # number of blocks from the border. + # Only for the vanilla world border. Ignored else. + warningDistance: 5 + + + # You can display the border size in the scoreboard; see `scoreboard.border`. + + + # Automatic and progressive border shrinking. + # Notice: if the border is circular, the WorldBorder Bukkit plugin by Brettflan (see above) + # is REQUIRED. Without, the border shrinking will not work. + shrinking: + enabled: false + + # Formats: "mm", "mm:ss" or "hh:mm:ss". + # With the default values, the border eats one block every 8 seconds on each side. + startsAfter: "30:00" + shrinksDuring: "2:00:00" + diameterAfterShrink: 200 + + # The delay between two warning messages sent to the players out of a future border # (this warning is set using /uh border warning <futureDiameter>). warningInterval: 90 # seconds @@ -71,6 +116,25 @@ scoreboard: episode: true players: true teams: true + ownTeam: + enabled: true # Displays the player's team in the scoreboard + title: + color: "" # The color of the title. If empty, the team color is used. + useTeamName: false # If true, the title is the team's name. Else, a generic title (« Your team »). + content: + displayHearts: true # Displays hearts colored following the player's life (low = red, high = green) + colorName: false # Color the whole name, not only the heart, following the life. If disabled the name is white (alive) or gray (dead). + strikeDeadPlayers: false # Strike the dead players lines. + loginState: + italic: true # Logged-out players are displayed in italic + suffix: "\u27A5" # This string is displayed after the name of logged-out players + displayMetPlayersOnly: + enabled: false # If enabled, the sidebar will only contains players met at some time. + displayedWhenCloserThan: 10 # If enabled, a teammate will be displayed to the reference player if he/she is closer that this amount of blocks to the player. + border: + displayed: true + displayDiameter: false # If true, displays the border diameter (ex. "2000 blocks wide"). Else, the min/max coordinates (ex. "-1000 +1000"). Ignored if the border is circular. + kills: true timer: true freezeStatus: true @@ -79,6 +143,27 @@ scoreboard: +# Controls what is displayed in the tab list headers and footers. +# Tags: +# - {title}: contains the scoreboard title (key scoreboard.title). +# - {episodeText}: contains the localized “Episode x” text. +# - {playersText}: contains the localized “x players left” text. +# - {teamsText}: contains the localized “x teams left” text. +# - {episodeNumber}: contains the raw episode number (e.g. “2”). +# - {playersCount}: contains the raw alive players count (e.g. “18”). +# - {teamsCount}: contains the raw alive teams count (e.g. “6”). +# You can use color & formatting codes with either & or §. +# If you want, you can use "\n" to create a new line. +playersList: + waitingTime: + header: "{title}" + footer: "" + inGameTime: + header: "{title}" + footer: "§a{episodeText} §7- §a{playersText} §7- §a{teamsText}" + + + # Update the MOTD according to the current state of the game? # This will overwrite the original MOTD. motd: @@ -112,15 +197,96 @@ statistics: +before-start: + inventory: + # True to clear the inventory of the players before the beginning of the game. + clear: true + + # True to prevent users from using their inventory when the game is not started. + preventUsage: true + + # True to disable all the inventory points above for players with the uh.build permission. + allowForBuilders: true + + teamSelector: + # True to give to the players a team selector, opening the teams inventory GUI (same as /teams). + enabled: true + + # The item to use as the team selector. Right-clicking it will open the GUI. + item: NETHER_STAR + + # Displays the current team in the action bar before the game. Nothing is displayed if the player is + # not in a team. + teamInActionBar: true + + enablePVP: false + + start: slow: delayBetweenTP: 3 # in seconds - + broadcastProgress: true # Displays something like « Teleporting... (14/28) » in the action bar for every player. + + cages: + # Instead of flying above the ground, if this is enabled, players will wait for the game start in + # cages, built in the material you want. + enabled: true + + # The cage type. Can be: + # - team_color_transparent (stained glass using the team color, or white without color/for solo); + # - team_color_solid (the same with stained hardened clay); + # - custom (a custom block, configure the one to use after). + type: team_color_transparent + + # If you selected “custom” before, write here the block you want to use. It can be any valid Material. + # You can use safely any falling block here, they will never fall. + customBlock: + + # If true, the cages will be built completly, including the ceiling. Else, they will be open to the sky. + buildCeiling: false + + # If true, the walls will be built using the block above. Else, using barrier blocks. + visibleWalls: true + + # The internal square radius of the cage. + # With 0, you'll have a cage with one block to walk. + # With 1, you'll have a 3×3 cage. + # With 2, a 5×5 cage. Etc. + radius: 1 + + # The internal height of the cages, i.e. the height of the space available to the players inside the cage. + height: 3 + sound: name: NONE volume: 1 pitch: 1 + # Display a title to everyone when the game begins + displayTitle: true + + # Damages are enabled after this amount of time. + # Cannot be less than 15 seconds, to avoid initial-fall-related problems. + # Format: "mm", "mm:ss", "hh:mm:ss" + gracePeriod: "00:30" + + # If true, a message will be broadcasted when the grace period ends. + broadcastGraceEnd: true + + # PVP is enabled after this amount of time. + # If 0, enabled immediately. + # Format: "mm", "mm:ss", "hh:mm:ss" + peacePeriod: 0 + + # The hostile mobs will not be allowed to spawn on the surface during this amount of time after + # the beginning of the game. This prevents mobs from lightning errors to cause deaths during the + # early game, when players just started and are not protected. + # This option is here to prevent lightning-bugs-related deaths or damages, so spawns on surface + # areas normally dark (like overhangs or floating islands) are not cancelled. Also, mobs will + # still spawn on caves. + # Format: "mm", "mm:ss", "hh:mm:ss". To disable, set to 0. + surfaceMobsFreePeriod: "15:00" + death: @@ -158,6 +324,8 @@ colorizeChat: true gameplay-changes: + naturalRegeneration: false # If true, the health will regenerate with food (just like in the default vanilla game). + weather: true # If false, the "bad" weather (rain, thunder) is disabled. replaceGhastTearsWithGold: true @@ -192,6 +360,15 @@ gameplay-changes: witch: disableNaturalSpawn: false disableLightningSpawn: false # from a villager + + rabbit: + killerRabbitSpawn: true + # When a rabbit spawns, it will be transformed into a Killer Rabbit following + # this probability (between 0 and 1). + killerRabbitSpawnProbability: 0.05 + # The rabbit will be named after this configuration point, except if empty - then, the + # default vanilla name will be used ("The Killer Bunny"). + killerRabbitName: "The Killer Rabbit of Caerbannog" # If true a compass will show the nearest player, and the craft will be different. @@ -219,7 +396,22 @@ teams-options: # Randoms colors for solo games and solo teams (i.e. all the teams generated when the game starts)? # If false, no color (aka white) used. randomColors: true - + + # These options are related to the auto-generated banner of each team. + # This banner is used on the teams selector (if set to "banner"), and can be given to the + # players when the game starts. + banner: + shape: + writeLetter: true + addBorder: true + give: + placeOnSpawn: true # Places the team banner on the spawn point. + giveInHotbar: false # Gives a banner to each player. + giveInHead: false # Places the banner on the head of each player. + shields: + addOnShields: true # Crafted shields will have the team banner on them. MC 1.9+ only. + + # Chat-based GUI to choose a team gui: # Display the players in each team, in the tooltip linked to the players count? @@ -229,6 +421,12 @@ teams-options: autoDisplay: true # Delay between the login and the display? (Seconds) delay: 4 + + # Chest-based GUI to choose a team and manage the teams + chestGui: + display: + teamItem: "banner" # Values: "banner", "glass", "glass_pane", "clay", "wool", "dye" + glowOnSelectedTeam: true # Set to true to display an enchantment glow on the player team teamChat: # Forces disable the team-chat when the player die. @@ -269,6 +467,8 @@ finish: timeAfterLastDeath: 3 # The command will be executed this amount of seconds after the last death. message: true # If true, the name of the winner(s) will be broadcasted. + title: true # If true, a title will display the winner(s) of the game. + fireworks: enabled: true # If true, some fireworks will be launched at the location of the winners. duration: 10 # In seconds. @@ -288,6 +488,21 @@ spectatorModeWhenNewPlayerJoinAfterStart: true +# Rules are a way to display rules & other informations to the players. +# The content is completly up to you, formatting included (using standard +# formatting codes with either § or &). It will be displayed as a list to +# the players (one bullet per line in the `rules.rules` entry). +# Empty entries (« - "" ») are replaced by a completly blank line, if you +# need a separator. +rules: + display: + onJoin: false + onStart: true + rules: + - + + + # Execute commands during the game or after the end of it, and after a configurable delay? # Format explained below. # Respect the spaces before the keywords ("exec" and "delay" need to be aligned). diff --git a/src/main/resources/i18n/cs_CZ.po b/src/main/resources/i18n/cs_CZ.po new file mode 100644 index 0000000..e84c473 --- /dev/null +++ b/src/main/resources/i18n/cs_CZ.po @@ -0,0 +1,2300 @@ +# Copyright or © or Copr. Nojp (2014 - 2016) +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: Nojp\n" +"POT-Creation-Date: 2016-01-20 03:37+0100\n" +"PO-Revision-Date: 2016-01-20 14:19:50.251245\n" +"Last-Translator: Nojp\n" +"Language-Team: Nojp\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. The name of the warning timer displaying the time left before the next +#. border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:84 +msgid "Border shrinking" +msgstr "Hranice se zmensuje" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:363 +msgid "{cs}All players are inside the given border." +msgstr "{cs}Vsichni hraci jsou uvnitr dane velikosti mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:367 +msgid "{ci}There are {0} players outside the given border." +msgstr "{ci}Nyni je {0} hracu za hranici dane velikosti mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:373 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "{lightpurple} - {red}{0}{ci} (daleko od hranice)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:377 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "{lightpurple} - {yellow}{0}{ci} (blizko hranici)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:381 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "{lightpurple} - {green}{0}{ci} (velmi blizko hranici)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{red}Warning!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{white}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:425 +msgid "{red}{bold}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:426 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "" +"{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "" +"{gray}Muzes zamykat a odemykat tymovy chat prikazem {cc}/togglechat{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "" +"{gray}Muzes odeslat zpravu vsem hracum na serveru prikazem {cc}/g " +"<message>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "" +"{gray}Muzes odeslat zpravu svemu tymu prikazem {cc}/t <message>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "" +"{gray}Muzes craftit zlata jablka pomoci hlav (stejny recept s hlavou misto " +"jablka)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder." +msgstr "" +"{gray}Kompas se da vycrafit s kosti, zkazenym masem, pavoucim okem a " +"strelnym prachem v rozich receptu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an ender pearl." +msgstr "" +"{gray}Kompas se da vycraftit s kosti, zkazenym masem, pavoucim okem a " +"strelnym prachem v rozich receptu + enderperlou veprostred." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "" +"{gray}Kompas se da vycraftit s kosti, zkazenym masem, pavoucim okem a " +"strelnym prachem v rozich receptu + Eye of Ender veprostred." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "{gray}Glistering melon se da vycrafit z melounu a goldblocku." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "{gray}V teto hre je enchantovane zlate jablko zakazano." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "" +"{gray}Spadl jsi na strom? Rychle seskoc, jsi nesmrtelny po dobu 25 sekund!" + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:131 +msgid "{darkpurple}ProTip!" +msgstr "{darkpurple}Tip pro vas!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:204 +msgid "Ultra Hardcore plugin loaded." +msgstr "UHC plugin byl nacten." + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:61 +msgid "{0} » {darkred}Delete" +msgstr "" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:69 +msgid "{green}Keep this team alive" +msgstr "" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:81 +msgid "{red}Delete this team {italic}forever" +msgstr "" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:68 +msgid "{0} » {black}Members" +msgstr "" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:77 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:123 +msgid "{green}« Go back" +msgstr "" + +#. The title of a button to select a player (a skull button). {0} = player's +#. display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:67 +msgid "Teams » {black}{0}" +msgstr "" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:73 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "" +msgstr[1] "" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{green}Update the color" +msgstr "" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:83 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:90 +msgid "{green}Rename the team" +msgstr "" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:92 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "{green} • " + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "{red} • " + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:106 +msgid "{green}Add or remove players" +msgstr "" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{red}Delete this team" +msgstr "" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:116 +msgid "{gray}Cannot be undone" +msgstr "" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:77 +msgid "{black}Select a team {reset}({0})" +msgstr "" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{white}Rename your team" +msgstr "" + +#. Warning displayed in the "Rename your team" button, if the player is not in +#. a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:91 +msgid "{gray}You have to be in a team" +msgstr "" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:100 +msgid "{white}New team" +msgstr "" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:118 +msgid "{blue}Players" +msgstr "" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "" + +#. Title of the team item in the teams selector GUI (with max). {0}: team +#. display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:177 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "" + +#. Title of the team item in the teams selector GUI (without max) {0}: team +#. display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:179 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "" + +#. The title of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "" + +#. The legend of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "" + +#. The summary title in the final « create the team » button of the create +#. team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "" + +#. The team name in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "" + +#. The team color in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "" + +#. The team members count in the final « create the team » button of the +#. create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:173 +msgid "{cs}Team created." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:177 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:118 +msgid "{ce}This team already exists." +msgstr "{ce}Tento tym jiz existuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:208 +#, java-format +msgid "Spawn point {0},{1} added from the config file" +msgstr "Spawn point {0};{1} byl nacten z konfiguracniho souboru" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:213 +#, java-format +msgid "Invalid spawn point set in config: {0}" +msgstr "V konfiguracnim souboru je neplatny spawn point: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:141 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:302 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "{aqua}Nyni jsi v tymu {0}{aqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:335 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:369 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "{darkaqua}Nadale nejsi v tymu {0}{darkaqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:84 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:211 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "{ce}Nemas povoleni poslat soukromou zpravu svemu tymu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:216 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "{ce}Nemas povoleni vstoupit do soukromeho chatu jineho tymu." + +#. Format of a private team message from a team member. {0} = sender display +#. name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:99 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "{gold}[{0}{gold} svemu tymu] {reset}{1}" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:105 +msgid "{ce}You are not in a team!" +msgstr "{ce}Nejsi v zadnem tymu!" + +#. Format of a private team message from a non-team-member. {0} = sender +#. display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:112 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "{gold}[{0}{gold} tymu {1}{gold}] {reset}{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:443 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:461 +#, java-format +msgid "Invalid team set in config: {0}" +msgstr "V konfiguracnim souboru je neplatny tym: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:450 +#, java-format +msgid "Team {0} ({1}) added from the config file" +msgstr "Tym {0} ({1}) byl nacten z konfiguracniho souboru" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:456 +#, java-format +msgid "Team {0} added from the config file" +msgstr "Tym {0} byl nacten z konfiguracniho souboru" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:497 +msgid "{gold}Click on the names below to join a team" +msgstr "{gold}Pokud se chcete pripojit do tymu, kliknete na jeho jmeno" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. +#. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:511 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "{gray}[{white}{0}{gray}/{white}{1}{gray}]" + +#. Team count without max players (ex. [3]) followed in-game by the team name. +#. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:516 +msgid "{gray}[{white}{0}{gray}]" +msgstr "{gray}[{white}{0}{gray}]" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:534 +msgid "{0} ({red}dead{reset})" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:539 +msgid "{0} ({green}alive{reset})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:544 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "{0} hracu v tomto tymu" +msgstr[1] "{0} hracu v tomto tymu" +msgstr[2] "{0} hracu v tomto tymu" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = +#. team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:557 +#, java-format +msgid "You are in the team {0}" +msgstr "Nyni jsi v tymu {0}" + +#. Tooltip on the chat team selector GUI when the player is not in the team. +#. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:562 +#, java-format +msgid "Click here to join the team {0}" +msgstr "Kliknete sem, pokud se chcete pripojit do tymu {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:574 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "{darkred}[×] {red}Kliknete sem, pokud chcete opustit svuj tym" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "{gray}Pokud tuto zpravu chcete zobrazit znovu, napiste /join" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "{ce}Neni zadny dostupny tym." + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:162 +msgid "jayjay" +msgstr "ayayay" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:240 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "{0}Tym {1} byl vyrazen ze hry!" + +#. A message displayed to the players under the death screen, about the +#. respawn possibility even if the death screen says the opposite (in hardcore +#. mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:284 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} MUZES SE " +"RESPAWNOUT{lightpurple}, jen klikni na {italic}Respawn {lightpurple}na dalsi" +" obrazovce." + +#. The kick message displayed if a player tries to relog after his death and +#. it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:442 +msgid "You are dead!" +msgstr "Zemrel jsi!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:515 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "" +"{darkred}[UHC] {ce}Plugin WorldBorder neni nainstalovan - hranice sveta " +"nemohou byt nastaveny!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:516 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game" +" (warnings excluded)." +msgstr "{gray}Bez tohoto pluginu nelze hranice sveta nastavovat behem hry." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:517 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "" +"{gray}Staci plugin nainstalovat, UHPlugin ho automaticky nakonfiguruje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:527 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "{darkred}[UHC] {ce}Potrebny ProtocolLib neni nainstalovan!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:528 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "{gray}Nasledujici moznosti vyzaduji pritomnost ProtocolLib:" + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = +#. option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:532 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "{darkgray} - {gray}{0}" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:545 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "{gray}ProtocolLib je dostupny zde: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:673 +msgid "{cs}The timer before the new border is up!" +msgstr "{cs}Casovac do nastaveni nove velikost mapy nyni bezi!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:705 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "{aqua}-------- Konec epizody 0} [vynuceno hracem {1}] --------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:709 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "{aqua}-------- Konec epizody {0} --------" + +#. The title displayed when the episode change. {0} = new episode number; {1} +#. = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:721 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "" + +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:745 +msgid "{green}--- GO ---" +msgstr "{green}--- UHC ZACINA ---" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:753 +msgid "{darkgreen}Let's go!" +msgstr "" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:755 +msgid "{green}Good luck, and have fun" +msgstr "" + +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:887 +msgid "{gold}{0} returned from the dead!" +msgstr "{gold}{0} se navratil ze zahrobi!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:200 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:279 +msgid "{aqua}Golden head" +msgstr "{aqua}Zlate jablko" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:280 +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Zlata hlava" + +#. Error message if a player tries to use his pointing compass without rotten +#. flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:304 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "{gray}{italic}Nemas zadne shnile maso (rotten flesh)." + +#. Error message if a player tries to use his pointing compass without a +#. player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:335 +msgid "{gray}{italic}Only silence answers your request." +msgstr "{gray}{italic}Tva zadost zmizela v tichu." + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:342 +msgid "{gray}The compass now points to the closest player." +msgstr "{gray}Kompas nyni ukazuje smer k nejblizsimu hraci." + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:152 +#, java-format +msgid "Death point of {0}" +msgstr "Zde zemrel hrac {0}" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:231 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "Zde se spawnul tym {0}" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation +#. ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:236 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:293 +#, java-format +msgid "Spawn point of {0}" +msgstr "Zde se spawnul hrac {0}" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +msgid "Made from the fallen head of a malignant monster" +msgstr "Vyrobeno z hlavy zhoubne prisery" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:290 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "Vyrobeno z hlavy padleho hrace {0}" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:393 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Zlate jablko" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:399 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Zlata hlava" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:426 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Zlate jablko" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:432 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Zlata hlava" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:141 +msgid "{gray}Episode {white}{0}" +msgstr "{gray}Epizoda {white}{0}" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:150 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:159 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "{white}{0}{gray} hracu" +msgstr[1] "{white}{0}{gray} hracu" +msgstr[2] "{white}{0}{gray} hracu" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:163 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "{white}{0}{gray} tymu" +msgstr[1] "{white}{0}{gray} tymu" +msgstr[2] "{white}{0}{gray} tymu" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:205 +msgid "{bold}Your team" +msgstr "" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:278 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:309 +msgid "{blue}{bold}Border" +msgstr "" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:317 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:320 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:336 +msgid "{white}{0} {1}" +msgstr "" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:341 +msgid "{gray}X: {white}{0} {1}" +msgstr "" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}Z: {white}{0} {1}" +msgstr "" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh +#. freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:384 +msgid "{darkaqua}Game frozen" +msgstr "{darkaqua}Hra pozastavena" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:121 +msgid "{red}{bold}Rules and informations" +msgstr "" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:132 +msgid "{darkgray}- {reset}{0}" +msgstr "" + +#. Episode in the player list ({episodeText} replacement). {0} = current +#. episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "Episode {0}" +msgstr "Epizoda {0}" + +#. Players in the player list ({playersText} replacement). {0} = current alive +#. players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "{0} hracu" +msgstr[1] "{0} hracu" +msgstr[2] "{0} hracu" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive +#. teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:121 +#, java-format +msgid "{0} team" +msgid_plural "{0} teams" +msgstr[0] "{0} tymu" +msgstr[1] "{0} tymu" +msgstr[2] "{0} tymu" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:89 +msgid "Waiting for players..." +msgstr "Ceka se na hrace..." + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:98 +msgid "Starting in progress..." +msgstr "Probiha start hry..." + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:113 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "Hra bezi! {0} hracu je nazivu." +msgstr[1] "Hra bezi! {0} hracu je nazivu." +msgstr[2] "Hra bezi! {0} hracu je nazivu." + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive +#. count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:118 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "Hra bezi! {0} hracu v {1} tymech je nazivu." +msgstr[1] "Hra bezi! {0} hracu v {1} tymech je nazivu." +msgstr[2] "Hra bezi! {0} hracu v {1} tymech je nazivu." + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:135 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "Hra skoncila, gratulujeme hraci {0} k jeho vitezstvi!" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:140 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "Hra skoncila, zapas vyhral tym {0}!" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "{0}{gray}:{white}{1}{gray}:{white}{2}" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "{white}{0}{gray}:{white}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "{aqua}------ Prikazy ke hre ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "{aqua}------ Prikazy k administraci ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "{aqua}------ Ostatni prikazy ------" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:107 +msgid "{ce}Usage: /{0} <message>" +msgstr "{ce}Pouziti: /{0} <zprava>" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "{aqua}------ Spawn points prikazy ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "" +"{cc}/uh spawns {ci}: nastavuje spawn points. Napiste /uh spawns pro vice " +"detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "{ce}Souradnice se musi skladat ze tri cisel." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "{ce}Takovy tym neexistuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "{ce}{0} je offline!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "{aqua}------ Teleportacni prikazy ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleportuje cely tym" +" na danou pozici nebo hrace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleportuje spectatory " +"(tedy hrace, kteri nejsou nazivu) na danou pozici nebo hrace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "" +"{cc}/uh tp {ci}: teleportuje spectatory nebo cely tym. Napiste /uh tp pro " +"vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "{yellow}{0} - verze {1}" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "a" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "Tento plugin vytvorili {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "Build: {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "Cislo buildu neni dostupne." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "{aqua}------ Preklady ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "Soucasny jazyk: {0} (prelozil {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "Zalozni jazyk: {0} (prelozil {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "{aqua}------ Licence ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "Publikovano pod CeCILL-B License." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "{cc}/uh about {ci}: zobrazi informace o pluginu a jeho prekladu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:67 +msgid "{cs}Warning canceled." +msgstr "{cs}Varovani bylo zruseno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:82 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "" +"{cs}Budouci velikost byla ulozena. Vsichni hraci za touto budouci hranici " +"mapy budou varovani kazdych {0} sekund." +msgstr[1] "" +"{cs}Budouci velikost byla ulozena. Vsichni hraci za touto budouci hranici " +"mapy budou varovani kazdych {0} sekund." +msgstr[2] "" +"{cs}Budouci velikost byla ulozena. Vsichni hraci za touto budouci hranici " +"mapy budou varovani kazdych {0} sekund." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:124 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "{ce}'{0}' neni cislo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: varuje" +" vsechny hrace za hranici mapy o danem budoucim prumeru. Jedna se pouze o " +"upozorneni." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "{cc}/uh border warning cancel{ci}: zrusi predesle varovani." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "" +"{ce}Nekteri hraci jsou za hranici mapy; provedeni prikazu bylo zruseno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "" +"{ci}Pouzijte {cc}/uh border set {0} force{ci} pro zmenu velikosti hranic bez" +" ohledu na tuto zpravu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "" +"{ce}VAROVANI: {ci}hraci za hranici mapy nebudou teleportovani, protoze " +"WorldBorder neni nainstalovan!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:114 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "{lightpurple}Prumer mapy je nyni {0} bloku." +msgstr[1] "{lightpurple}Prumer mapy je nyni {0} bloku." +msgstr[2] "{lightpurple}Prumer mapy je nyni {0} bloku." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:118 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "{lightpurple}Velikost mapy je nyni {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:149 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" +"{cc}/uh border set <diameter> [force]{ci}: zmeni velikost mapy. Pokud neni " +"zadan arguement 'force', operace bude zrusena za predpokladu, ze nektery z " +"hracu je za hranice mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "" +"{cc}/uh border check <diameter>{ci}: zobrazi seznam hracu za hranici dane " +"velikosti mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "{ci}Soucasny prumer mapy je {0} bloku." +msgstr[1] "{ci}Soucasny prumer mapy je {0} bloku." +msgstr[2] "{ci}Soucasny prumer mapy je {0} bloku." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "{ci}Soucasna velikost mapy je {0}×{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "{cc}/uh border get{ci}: vrati mapu do jeji puvodni velikosti." + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "{ci}{0} hracu nazivu v {1} tymech." +msgstr[1] "{ci}{0} hracu nazivu v {1} tymech." +msgstr[2] "{ci}{0} hracu nazivu v {1} tymech." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "{ci}Hra jeste nezacala." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "Prave online" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "Prave offline" + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "Tym: {0}" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "{gray} - " + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "{green}nazivu" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "{0} pulsrdicek" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "{red}mrtvych" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "{cc}/uh infos {ci}: zobrazi informace o soucasne hre." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "" +"{ce}Mnozstvi jidla (foodPoints) i saturace musi byt cisla (saturace je " +"desetinne cislo)!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: nakrmi vsechny hrace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "{cs}Spawn byl pridan ve svete {0}: {1};{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "{ce}Nemuzete pridat spawn point za hranicemi mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "{ce}Operace selhala: zadne bezpecne misto v Netheru nebylo nalezeno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "{ce}Musite urcit obe souradnice." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "{ce}To neni cislo!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "" +"{cc}/uh spawns add [<x> <z>]{ci}: prida spawn point pro tym nebo hrace na " +"soucasne pozici odesilatele prikazu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "" +"{ci}Zadny tym nebyl nalezen, plugin predpoklada, ze se jedna o solo hru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "" +"{ci}Nekteri hraci nejsou soucasti zadneho tymu, jejich cislo bylo pridano do" +" spawn poctu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "{ce}Svet {0} neexistuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "{ci}Zazadali jste o generaci voidu, proto je tato generace prazdna." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "{ce}Generacni metoda '{0}' neni (zatim?) podporovana." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "" +"{ce}Chcete nemozne: zazadali jste moc spawn points na male plose. Snizte " +"pocet spawn points nebo minimalni vzdalenost mezi nimi." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "{cs}Zazadane spawn points byly uspesne vytvoreny." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "{aqua}Prikaz" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "{aqua}Tvary" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr "" +" - {cc}random{ci}: vygeneruje nahodne spawn points na mape s minimalni " +"vzdalenosti mezi sebou." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr "" +" - {cc}grid{ci}: vygeneruje spawn points v soustrednych ctvercich s " +"minimalni vzdalenosti mezi dvema body." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" +" - {cc}circular{ci}: vygeneruje spawn points v soustrednych kruzich s " +"minimalni vzdalenosti mezi dvema body. V kazdem kruhu je vzdalenost a uhel " +"mezi dvema body konstantni." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "{aqua}Argumenty" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr "" +" - {cc}size{ci}: velikost regionu, ve kterem budou spawn points " +"vygenerovany. Budou kruhovite nebo ctvercovite podle tvaru mapy (standardni " +"hodnota)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr "" +" - {cc}distanceMin{ci}: minimalni vzdalenost mezi dvema spawn points. " +"Standardni je 250 bloku." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr "" +" - {cc}count{ci}: pocet spawn points, ktere maji byt vygenerovany. " +"Standardne se jedna o pocet hracu nebo tymu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: souradnic stredu regionu, ve kterem " +"budou spawn points vygenerovany. Standardne se jedna o spawn mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr " - {cc}world{ci}: svet, ve kterem budou spawn points vygenerovany." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "" +"{cc}/uh spawns generate {ci}: automagicky vygeneruje spawn points. Napiste " +"/uh spawns generat pro vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "" +"{cc}/uh spawns dump {ci}: zobrazi dostupne spawn points v exportovatelnem " +"formatu. {gray}Toto muzete pouzit napriklad k rozplanovani spawn points." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "{ce}Neni zadny registrovany spawn point." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "{ci}Nyni je registrovano {0} spawn points." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "{lightpurple}Svet {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:180 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "{cc}/uh spawns list {ci}: zobrazi seznam dostupnych spawn points." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "{cs}Vsechny spawn points byly odstraneny." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "{cc}/uh spawns reset {ci}: odstrani vsechny spawn points." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "{cs}Spawn point {1};{2} ve svete {0} byl odstranen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" +"{cc}/uh spawns remove [<x> <z>] {ci}: odstrani spawn points na danych " +"souradnicich, pripadne na soucasne pozici odesilatele pri neudani souradnic." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:110 +msgid "{ce}The player {0} is not online." +msgstr "{ce}Hrac {0} neni online." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "{ce}Nebylo nalezeno misto umrti hrace {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "{cs}Hrac {0} byl uspesne teleportovan zpet." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "" +"{ce}Hrac {0} NEBYL teleportovan, protoze nebylo nalezeno zadne bezpecne " +"misto." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" +"{ci}Pouzijte {cc}/uh tpback {0} force{ci} pro teleport i pres nenalezeni " +"bezpecneho mista." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "" +"{cc}/uh tpback <player> [force] {ci}: bezpecne teleportuje hrace na misto " +"jeho smrti." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "{ce}Hra jeste nezacala!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "{ce}Hra jeste neskoncila!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "{cc}/uh finish {ci}: zobrazi jmena vitezneho tymu a spusti ohnostroj." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this" +" point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his" +" spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "{ce}Tento hrace nehraje nebo neni mrtvy!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "" +"{cs}Protoze hrace {0} je offline, bude vzkristen po pripojeni. Pripadny ban " +"byl odstranen." + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "{ce}{0} neni mrtvy!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "{cc}/uh resurrect <player> {ci}: vzkrisi hrace z mrtvych." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:111 +msgid "" +"{ce}Unable to add the player {0} to the team {1}. This player is unknown in " +"the server." +msgstr "" +"{ce}Nepovedlo se pridat hrace {0} do tymu {1}. Hrac musi byt pripojen k " +"serveru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:119 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "{ce}Takovy tym neexistuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:132 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "{cs}Hrac {0} byl uspesne pridan do tymu {1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:178 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" +"{cc}/uh team join <player> <teamName ...> {ci}: prida hrace do daneho tymu. " +"Jmeno tymu je jeho barva, pripadne konkretni jmeno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "{cs}Vsechny tymy byly odstraneny." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "{cc}/uh team reset {ci}: odstrani vsechny tymy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "" +"{ce}Nepovedlo se pridat tym, zkontrolujte jmeno barvy. Tip: pouzijte Tab pro" +" automaticke dokonceni." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:122 +msgid "{cs}Team {0}{cs} added." +msgstr "{cs}Tym {0}{cs} byl pridan." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:164 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "{cc}/uh team add <color> [<name ...>] {ci}: prida tym dane barvy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:90 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "{ce}Hrac {0} je odpojen od serveru!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:107 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "{cs}Hrac {0} byl uspesne odstranen ze sveho tymu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:141 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "{cc}/uh team leave <player> {ci}: odstrani hrace z jeho tymu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "{cs}Tym {0} byl odstranen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "{cc}/uh team remove <name ...> {ci}: odstrani tym" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "{ce}Nejsou zadne definovane tymy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "{0} ({1} hracu)" +msgstr[1] "{0} ({1} hracu)" +msgstr[2] "{0} ({1} hracu)" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "{cc}/uh team list {ci}: zobrazi seznam tymu a jejich hracu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "{aqua}------ Prikazy k casovacum ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "" +"{cc}/uh timers {ci}: nastavi casovace. Napiste /uh times pro vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:106 +msgid "{aqua}------ Team commands ------" +msgstr "{aqua}------ Tymove prikazy ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:107 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the" +" given team. Without arguments, displays the chat-based team selector." +msgstr "" +"{cc}/join [player] <team ...> {ci}: prida hrace (nebo odesilatele prikazu) " +"do daneho tymu. Bez dalsich argumentu zobrazi vybirani tymu v chatu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:108 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "" +"{cc}/leave [player] {ci}: odstrani hrace (nebo odesilatele prikazu) z jeho " +"tymu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:115 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "{cc}/uh team {ci}: nastavuje tymy. Napiste /uh team pro vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "{aqua}------ Prikazy k hranicim ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "" +"{cc}/uh border {ci}: nastavuje hranice. Napiste /uh borders pro vice " +"detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "{ce}Hej, tohle neni pocet pulsrdicek. Tohle je text. Pfff." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "{ce}Seriovy vrahu!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "{ce}Zdravi hrace {0} nebylo updatovano, aby se predeslo zabiti." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: uzdravi misto jednoho hrace " +"vsechny." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "konzole" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "" +"{ce}Neni mozne posunout soucasnou epizodu, protoze hra jeste nezacala." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "{cc}/uh shift {ci}: posune epizodu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "{cst}Generuji hranice mapy..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "{ci}Z konzole generuji hranice teto mapy, {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the" +" config are probably invalid." +msgstr "" +"{ce}Plugin nebyl schopny vygenerovat hranici mapy, vice informaci v logu. " +"Pravdepodobnou pricinou je neplatnost nastavenych bloku." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "{ce}Vyskytla se chyba, vice informaci naleznete v konzoli." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "{cst}Generace byla dokoncena." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "" +"{cc}/uh generatewalls {ci}: generuje zdi podle nakonfigurovanych parametru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "{ce}Takovy casovac neexistuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "{cs}}Casovac {0}{cs} byl zastaven." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "" +"{cc}/uh timers stop <title ...> {ci}: zastavi casovac. Ten bude take skryt " +"ze scoreboardu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "{cs}}Casovac {0}{cs} zacal odpocitavat." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "{cc}/uh timers start <title ...> {ci}: nastartuje casovac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "{cs}}Casovac {0}{cs} je nyni skryt." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "" +"{cc}/uh timers hide <title ...> {ci}: skryje casovac ze scoreboardu. Tato " +"funkce casovac nezastavi." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "{ci}{0} casovac(u) je registrovano." +msgstr[1] "{ci}{0} casovac(u) je registrovano." +msgstr[2] "{ci}{0} casovac(u) je registrovano." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{yellow} • {ci}{0}{ci} - celkem {1} sekund - {2}" +msgstr[1] "{yellow} • {ci}{0}{ci} - celkem {1} sekund - {2}" +msgstr[2] "{yellow} • {ci}{0}{ci} - celkem {1} sekund - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:81 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{green} • {ci}{0}{ci} - celkem {1} sekund - {2}" +msgstr[1] "{green} • {ci}{0}{ci} - celkem {1} sekund - {2}" +msgstr[2] "{green} • {ci}{0}{ci} - celkem {1} sekund - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:90 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "{red} • {ci}{0}{ci} - celkem {1} sekund" +msgstr[1] "{red} • {ci}{0}{ci} - celkem {1} sekund" +msgstr[2] "{red} • {ci}{0}{ci} - celkem {1} sekund" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:119 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "{cc}/uh timers list {ci}: zobrazi seznam bezicich casovacu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "{cs}Casovac {0}{cs} je nyni zobrazen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard." +" Automatic when a timer is started." +msgstr "" +"{cc}/uh timers display <title ...> {ci}: zobrazi casovac ve scoreboardu. " +"Tato funkce je automaticka po startu casovace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "{cs}}Casovac {0}{cs} byl odstranen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "{cc}/uh timers remove <title ...> {ci}: odstrani casovac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "{cs}}Casovac {0}{cs} nyni pokracuje." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "{cc}/uh timers resume <title ...> {ci}: pokracuje v casovaci." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "{cs}Delka casovace {0}{cs} je nyni {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or " +"hh:mm:ss." +msgstr "{ce}Chyba v casove syntaxi - funguji formaty mm, mm:ss a hh:mm:ss." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a " +"timer." +msgstr "" +"{cc}/uh timers set <duration> <title ...> {ci}: nastavi delku casovace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "{ce}Casovac nazvany {0}{ce} jiz existuje, prosim vyberte jine jmeno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "{cs}Casovac {0}{cs} s delkou {1} byl registrovan." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "{cc}/uh timers add <duration> <title ...> {ci}: prida casovac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "{cs}}Casovac {0}{cs} je nyni pauznut." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "{cc}/uh timers pause <title ...> {ci}: pauzne casovac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "{cst}Byl jsi zmrazen administratorem {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "{cst}Byl jsi odmrazen administratorem {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "{cs}{0} je nyni zmrazen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "{cs}{0} je nyni odmrazen." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "{darkaqua}Cela hra je nyni pozastavena." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "{darkaqua}Hra opet bezi." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "{aqua}------ Zmrazovaci prikazy ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "" +"{cc}/uh freeze on [player]{ci}: zmrazi hrace, pripadne odesilatele prikazu " +"pri neudani hrace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if" +" the entire game is frozen." +msgstr "" +"{cc}/uh freeze off [player]{ci}: odmrazi hrace (nebo odesilatele), i kdyz je" +" cela hra zmrazena." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "" +"{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "{cc}/uh freeze all{ci}: zmrazi celou hru (hraci, mobove, casovace)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this" +" in order to relaunch the timer." +msgstr "" +"{cc}/uh freeze none{ci}: odmrazi celou hru. Tento prikaz je nutnosti, pokud " +"chcete znovu spustit casovac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "" +"{cc}/uh freeze {ci}: (od)zmrazi celou hru nebo jednoho hrace. Napiste /uh " +"freeze pro vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "{ce}Tento hrac je offline." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "{ce}Kvuli predejiti preklepu neni mozne zabit hrace timto prikazem." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: uzdravi hrace o pocet " +"zadanych pulsrdicek (standardne 20)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: nakrmi hrace." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "{ce}Tento hrac nikdy nenavstivil tento server." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "{cs}Hrac {0} je nyni prohlasen za mrtveho." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "{ce}{0} neni zivy hrac." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "" +"{cc}/uh kill <player> {ci}: oznaci hrace za mrtveho, i kdyz je offline." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:102 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the" +" game." +msgstr "" +"{ce}Hra jiz zacala! Reloadnete nebo restartujete server pro restart hry." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:150 +msgid "{aqua}------ Beginning of the game ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:151 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:152 +msgid "{aqua}Startup options" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:153 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append" +" them to the command with spaces." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:154 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:155 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:162 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "{cc}/uh start {ci}: spusti hru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:94 +msgid "{cs}The player {0} is now a spectator." +msgstr "{cs}Hrac {0} je nyni spectatorem." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:115 +msgid "{cs}The player {0} is now a player." +msgstr "{cs}Hrac {0} je nyni hracem." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:125 +msgid "{ce}There isn't any spectator to list." +msgstr "{ce}Neni mozne vypsat spectatory, jelikoz zadni neexistuji." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "{ci}{0} registrovanych spectatoru." +msgstr[1] "{ci}{0} registrovanych spectatoru." +msgstr[2] "{ci}{0} registrovanych spectatoru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:130 +msgid "{ci}This count includes only the initial spectators." +msgstr "{ci}Tento seznam zahrnuje pouze pocatecni spectatory." + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "{lightpurple} - {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:171 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "{aqua}------ Prikazy ke startup spectatorum ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:173 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "{cc}/uh spec add <player>{ci}: prida startup spectatora." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:174 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "{cc}/uh spec remove <player>{ci}: odebere startup spectatora." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:175 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "{cc}/uh spec list{ci}: zobrazi seznam startup spectatoru." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:183 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "" +"{cc}/uh spec {ci}: nastavuje spectatory. Napiste /uh spec pro vice detailu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "{cs}Nyni pises do tymoveho chatu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "{cs}Nyni pises do globalniho chatu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "{cs}Nyni pises do chatu s tymem {0}{cs}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed " +"...>{ci}." +msgstr "" +"{ci}Legenda: {cc}/uh prikaz <povinne> [volitelne=vychozi] <povolene mezery, " +"...>{ci}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "{ce}lolnope" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +#, fuzzy +msgid "" +"{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "{ce}Nyni jsi za budouci hranici mapy (prumer {0} bloku)." +msgstr[1] "{ce}Nyni jsi za budouci hranici mapy (prumer {0} bloku)." +msgstr[2] "{ce}Nyni jsi za budouci hranici mapy (prumer {0} bloku)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "" +"{ce}Nyni jsi za budouci hranici mapy, ktera bude mit velikost {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +#, fuzzy +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "{ci}Musis ujit jeste {0} bloku, nez budes uvnitr mapy." +msgstr[1] "{ci}Musis ujit jeste {0} bloku, nez budes uvnitr mapy." +msgstr[2] "{ci}Musis ujit jeste {0} bloku, nez budes uvnitr mapy." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:325 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "{ce}Neni mozne zacit hru: neni dostatek teleportacnich mist." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:326 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:399 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "{lightpurple}Probiha teleportace... vyckejte, prosim." + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:414 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:434 +msgid "{gray}Player {0}{gray} teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:486 +msgid "{cs}All teams are teleported." +msgstr "{cs}Vsechny tymy byly uspesne teleportovany." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:487 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "{gray}Pouzijte prikaz {cc}/uh start{gray} pro zapoceti hry." + +#. Displayed in the action bar when the slow teleportation is finished but the +#. game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:525 +msgid "{ce}Please execute {cc}/uh start slow{ce} before." +msgstr "{ce}Nejprve napiste prikaz {cc}/uh start slow{ce}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:531 +msgid "{ce}Please wait while the players are teleported." +msgstr "{ce}Prosim vyckejte, nez budou vsichni hraci teleportovani." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:631 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "" + +#. The "and" in the winners players list (like "player1, player2 and +#. player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1083 +msgctxt "winners_list" +msgid "and" +msgstr "a" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1095 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Gratulujeme tymu {0} (team {1}{green}) k " +"jejich vitezstvi v tomto UHC! {darkgreen}{obfuscated}--" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1099 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Gratulujeme hraci {0} k jeho vitezstvi v " +"tomto UHC! {darkgreen}{obfuscated}--" + +#. The main title of the /title displayed when a team wins the game. {0} +#. becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in +#. solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1118 +msgid "{darkgreen}{0}" +msgstr "" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes +#. the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1113 +msgid "{green}This team wins the game!" +msgstr "" + +#. The subtitle of the /title displayed when a player wins the game (in solo). +#. {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1120 +msgid "{green}wins the game!" +msgstr "" diff --git a/src/main/resources/i18n/cs_CZ.yml b/src/main/resources/i18n/cs_CZ.yml deleted file mode 100644 index 9074dd9..0000000 --- a/src/main/resources/i18n/cs_CZ.yml +++ /dev/null @@ -1,506 +0,0 @@ -author: "Nojp" -keys: - load: - spawnPointAdded: "Spawn point {0};{1} byl nacten z konfiguracniho souboru" - invalidSpawnPoint: "V konfiguracnim souboru je neplatny spawn point: {0}" - teamAdded: "Tym {0} byl nacten z konfiguracniho souboru" - namedTeamAdded: "Tym {0} ({1}) byl nacten z konfiguracniho souboru" - invalidTeam: "V konfiguracnim souboru je neplatny tym: {0}" - recipeApple: "Pridan novy recept na zlate jablko." - recipeCompass: "Pridan novy recept na kompas." - recipeMelon: "Pridan novy recept na zlaty meloun." - loaded: "UHC plugin byl nacten." - - WBNotInstalled1: "{darkred}[UHC] {ce}Plugin WorldBorder neni nainstalovan - hranice sveta nemohou byt nastaveny!" - WBNotInstalled2: "{gray}Bez tohoto pluginu nelze hranice sveta nastavovat behem hry." - WBNotInstalled3: "{gray}Staci plugin nainstalovat, UHPlugin ho automaticky nakonfiguruje." - - SPNotInstalled1: "{darkred}[UHC] {ce}Plugin SpectatorPlus neni nainstalovan." - SPNotInstalled2: "{gray}Pokud chcete spectator mod, staci plugin nainstalovat, UHPlugin ho automaticky nakonfiguruje." - - PLNotInstalled1: "{darkred}[UHC] {ce}Potrebny ProtocolLib neni nainstalovan!" - PLNotInstalled2: "{gray}Nasledujici moznosti vyzaduji pritomnost ProtocolLib:" - PLNotInstalledItem: "{darkgray} - {gray}{0}" - PLNotInstalled3: "{gray}ProtocolLib je dostupny zde: {0}" - - cmd: - errorLoad: "{ce}Vyskytla se chyba, vice informaci naleznete v konzoli. Pravdepodobne se jedna o bug." - errorUnknown: "{ce}Tento prikaz neexistuje. Napiste /uh pro seznam dostupnych prikazu." - errorUnauthorized: "{ce}lolnope" - - titleHelp: "{yellow}{0} - verze {1}" - legendHelp: "{ci}Legenda: {cc}/uh prikaz <povinne> [volitelne=vychozi] <povolene mezery, ...>{ci}." - helpNextPage: "{gray}Dalsi stranka: /uh {0}" - - titleGameCmd: "{aqua}------ Prikazy ke hre ------" - helpStart: "{cc}/uh start {ci}: spusti hru." - helpStartSlow: "{cc}/uh start slow {ci}: pomalu spusti hru ve dvou krocich (vhodne pro mensi servery)." - helpShift: "{cc}/uh shift {ci}: posune epizodu." - helpTeam: "{cc}/uh team {ci}: nastavuje tymy. Napiste /uh team pro vice detailu." - helpSpawns: "{cc}/uh spawns {ci}: nastavuje spawn points. Napiste /uh spawns pro vice detailu." - helpSpec: "{cc}/uh spec {ci}: nastavuje spectatory. Napiste /uh spec pro vice detailu." - helpWall: "{cc}/uh generatewalls {ci}: generuje zdi podle nakonfigurovanych parametru." - helpBorder: "{cc}/uh border {ci}: nastavuje hranice. Napiste /uh borders pro vice detailu." - - titleBugCmd: "{aqua}------ Prikazy k administraci ------" - helpHeal: "{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: uzdravi hrace o pocet zadanych pulsrdicek (standardne 20)." - helpHealall: "{cc}/uh healall [half-hearts=20|±diff] {ci}: uzdravi misto jednoho hrace vsechny." - helpFeed: "{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: nakrmi hrace." - helpFeedall: "{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: nakrmi vsechny hrace." - helpKill: "{cc}/uh kill <player> {ci}: oznaci hrace za mrtveho, i kdyz je offline." - helpResurrect: "{cc}/uh resurrect <player> {ci}: vzkrisi hrace z mrtvych." - helpTpback: "{cc}/uh tpback <player> [force] {ci}: bezpecne teleportuje hrace na misto jeho smrti." - - titleMiscCmd: "{aqua}------ Ostatni prikazy ------" - helpFreeze: "{cc}/uh freeze {ci}: (od)zmrazi celou hru nebo jednoho hrace. Napiste /uh freeze pro vice detailu." - helpFinish: "{cc}/uh finish {ci}: zobrazi jmena vitezneho tymu a spusti ohnostroj." - helpTP: "{cc}/uh tp {ci}: teleportuje spectatory nebo cely tym. Napiste /uh tp pro vice detailu." - helpTimers: "{cc}/uh timers {ci}: nastavi casovace. Napiste /uh times pro vice detailu." - helpInfos: "{cc}/uh infos {ci}: zobrazi informace o soucasne hre." - helpAbout: "{cc}/uh about {ci}: zobrazi informace o pluginu a jeho prekladu." - - teamHelpTitle: "{aqua}------ Tymove prikazy ------" - teamHelpAdd: "{cc}/uh team add <color> {ci}: prida tym dane barvy." - teamHelpAddName: "{cc}/uh team add <color> <name ...> {ci}: prida pojmenovany tym daneho jmena a barvy." - teamHelpRemove: "{cc}/uh team remove <name ...> {ci}: odstrani tym" - teamHelpJoin: "{cc}/uh team join <player> <teamName ...> {ci}: prida hrace do daneho tymu. Jmeno tymu je jeho barva, pripadne konkretni jmeno." - teamHelpLeave: "{cc}/uh team leave <player> {ci}: odstrani hrace z jeho tymu." - teamHelpList: "{cc}/uh team list {ci}: zobrazi seznam tymu a jejich hracu." - teamHelpReset: "{cc}/uh team reset {ci}: odstrani vsechny tymy." - teamHelpJoinCmd: "{cc}/join [player] <team ...> {ci}: prida hrace (nebo odesilatele prikazu) do daneho tymu. Bez dalsich argumentu zobrazi vybirani tymu v chatu." - teamHelpLeaveCmd: "{cc}/leave [player] {ci}: odstrani hrace (nebo odesilatele prikazu) z jeho tymu." - - spawnsHelpTitle: "{aqua}------ Spawn points prikazy ------" - spawnsHelpAdd: "{cc}/uh spawns add {ci}: prida spawn point pro tym nebo hrace na soucasne pozici odesilatele prikazu." - spawnsHelpAddXZ: "{cc}/uh spawns add <x> <z> {ci}: prida spawn point pro tym nebo hrace na danych souradnicich v soucasnem svete." - spawnsHelpGenerate: "{cc}/uh spawns generate {ci}: automagicky vygeneruje spawn points. Napiste /uh spawns generat pro vice detailu." - spawnsHelpGenerateDetailsCmdTitle: "{aqua}Prikaz" - spawnsHelpGenerateDetailsCmd: "{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] [xCenter] [zCenter] [world]" - spawnsHelpGenerateDetailsShapesTitle: "{aqua}Tvary" - spawnsHelpGenerateDetailsShapesRandom: " - {cc}random{ci}: vygeneruje nahodne spawn points na mape s minimalni vzdalenosti mezi sebou." - spawnsHelpGenerateDetailsShapesGrid: " - {cc}grid{ci}: vygeneruje spawn points v soustrednych ctvercich s minimalni vzdalenosti mezi dvema body." - spawnsHelpGenerateDetailsShapesCircular: " - {cc}circular{ci}: vygeneruje spawn points v soustrednych kruzich s minimalni vzdalenosti mezi dvema body. V kazdem kruhu je vzdalenost a uhel mezi dvema body konstantni." - spawnsHelpGenerateDetailsArgsTitle: "{aqua}Argumenty" - spawnsHelpGenerateDetailsArgsSize: " - {cc}size{ci}: velikost regionu, ve kterem budou spawn points vygenerovany. Budou kruhovite nebo ctvercovite podle tvaru mapy (standardni hodnota)." - spawnsHelpGenerateDetailsArgsDistanceMin: " - {cc}distanceMin{ci}: minimalni vzdalenost mezi dvema spawn points. Standardni je 250 bloku." - spawnsHelpGenerateDetailsArgsCount: " - {cc}count{ci}: pocet spawn points, ktere maji byt vygenerovany. Standardne se jedna o pocet hracu nebo tymu." - spawnsHelpGenerateDetailsArgsCenter: " - {cc}xCenter{ci}, {cc}zCenter{ci}: souradnic stredu regionu, ve kterem budou spawn points vygenerovany. Standardne se jedna o spawn mapy." - spawnsHelpGenerateDetailsArgsWorld: " - {cc}world{ci}: svet, ve kterem budou spawn points vygenerovany." - spawnsHelpList: "{cc}/uh spawns list {ci}: zobrazi seznam dostupnych spawn points." - spawnsHelpDump: "{cc}/uh spawns dump {ci}: zobrazi dostupne spawn points v exportovatelnem formatu. {gray}Toto muzete pouzit napriklad k rozplanovani spawn points." - spawnsHelpRemove: "{cc}/uh spawns remove [<x> <z>] {ci}: odstrani spawn points na danych souradnicich, pripadne na soucasne pozici odesilatele pri neudani souradnic." - spawnsHelpReset: "{cc}/uh spawns reset {ci}: odstrani vsechny spawn points." - - specHelpTitle: "{aqua}------ Prikazy ke startup spectatorum ------" - specHelpNoticeSpectatorPlusNotInstalled: "{ce}Berte na vedomi{ci}: jelikoz SpectatorPlus neni nainstalovan, spectator je {italic}pouze{ci} ignorovanym hracem." - specHelpAdd: "{cc}/uh spec add <player>{ci}: prida startup spectatora." - specHelpRemove: "{cc}/uh spec remove <player>{ci}: odebere startup spectatora." - specHelpList: "{cc}/uh spec list{ci}: zobrazi seznam startup spectatoru." - - freezeHelpTitle: "{aqua}------ Zmrazovaci prikazy ------" - freezeHelpOn: "{cc}/uh freeze on [player]{ci}: zmrazi hrace, pripadne odesilatele prikazu pri neudani hrace." - freezeHelpOff: "{cc}/uh freeze off [player]{ci}: odmrazi hrace (nebo odesilatele), i kdyz je cela hra zmrazena." - freezeHelpAll: "{cc}/uh freeze all{ci}: zmrazi celou hru (hraci, mobove, casovace)." - freezeHelpNone: "{cc}/uh freeze none{ci}: odmrazi celou hru. Tento prikaz je nutnosti, pokud chcete znovu spustit casovac." - - borderHelpTitle: "{aqua}------ Prikazy k hranicim ------" - borderHelpCurrent: "{cc}/uh border current{ci}: vrati mapu do jeji puvodni velikosti." - borderHelpSet: "{cc}/uh border set <diameter> [force]{ci}: zmeni velikost mapy. Pokud neni zadan arguement 'force', operace bude zrusena za predpokladu, ze nektery z hracu je za hranice mapy." - borderHelpWarning: "{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: varuje vsechny hrace za hranici mapy o danem budoucim prumeru. Jedna se pouze o upozorneni." - borderHelpWarningCancel: "{cc}/uh border warning cancel{ci}: zrusi predesle varovani." - borderHelpCheck: "{cc}/uh border check <diameter>{ci}: zobrazi seznam hracu za hranici dane velikosti mapy." - - tpHelpTitle: "{aqua}------ Teleportacni prikazy ------" - tpHelpTeam: "{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleportuje cely tym na danou pozici nebo hrace." - tpHelpSpectators: "{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleportuje spectatory (tedy hrace, kteri nejsou nazivu) na danou pozici nebo hrace." - - timersHelpTitle: "{aqua}------ Prikazy k casovacum ------" - timersHelpAdd: "{cc}/uh timers add <duration> <title ...> {ci}: prida casovac." - timersHelpSet: "{cc}/uh timers set <duration> <title ...> {ci}: nastavi delku casovace." - timersHelpDisplay: "{cc}/uh timers display <title ...> {ci}: zobrazi casovac ve scoreboardu. Tato funkce je automaticka po startu casovace." - timersHelpHide: "{cc}/uh timers hide <title ...> {ci}: skryje casovac ze scoreboardu. Tato funkce casovac nezastavi." - timersHelpStart: "{cc}/uh timers start <title ...> {ci}: nastartuje casovac." - timersHelpPause: "{cc}/uh timers pause <title ...> {ci}: pauzne casovac." - timersHelpResume: "{cc}/uh timers resume <title ...> {ci}: pokracuje v casovaci." - timersHelpStop: "{cc}/uh timers stop <title ...> {ci}: zastavi casovac. Ten bude take skryt ze scoreboardu." - timersHelpRemove: "{cc}/uh timers remove <title ...> {ci}: odstrani casovac." - timersHelpList: "{cc}/uh timers list {ci}: zobrazi seznam bezicich casovacu." - timersHelpDurations: "{gray}Format casu: mm, mm:ss nebo hh:mm:ss." - - about: - authors: "Tento plugin vytvorili {0}." - and: "a" - - build: - number: "Build: {0}." - notAvailable: "Cislo buildu neni dostupne." - - i18n: - title: "{aqua}------ Preklady ------" - selected: "Soucasny jazyk: {0} (prelozil {1})." - fallback: "Zalozni jazyk: {0} (prelozil {1})." - license: - title: "{aqua}------ Licence ------" - license: "Publikovano pod GNU General Public License (verze 3)." - - start: - already: "{ce}Hra jiz zacala! Reloadnete nebo restartujete server pro restart hry." - syntax: "{ce}Chyba v syntaxi prikazu. Pouziti: /uh start [slow] nebo /uh start slow go." - notEnoughTP: "{ce}Neni mozne zacit hru: neni dostatek teleportacnich mist." - teleportationInProgress: "{lightpurple}Probiha teleportace... vyckejte, prosim." - - startSlowBeforeStartSlowGo: "{ce}Nejprve napiste prikaz {cc}/uh start slow{ce}" - startSlowWaitBeforeGo: "{ce}Prosim vyckejte, nez budou vsichni hraci teleportovani." - startSlowTeamTP: "{gray}Tym {0}{gray} byl uspesne teleportovan." - startSlowAllTeamsTP: "{cs}Vsechny tymy byly uspesne teleportovany." - startSlowAllTeamsTPCmd: "{gray}Pouzijte prikaz {cc}/uh start slow go{gray} pro zapoceti hry." - - go: "{green}--- UHC ZACINA ---" - - finish: - notStarted: "{ce}Hra jeste nezacala!" - notFinished: "{ce}Hra jeste neskoncila!" - - and: "a" - - broadcast: - withTeams: "{darkgreen}{obfuscated}--{green} Gratulujeme tymu {0} (team {1}{green}) k jejich vitezstvi v tomto UHC! {darkgreen}{obfuscated}--" - withoutTeams: "{darkgreen}{obfuscated}--{green} Gratulujeme hraci {0} k jeho vitezstvi v tomto UHC! {darkgreen}{obfuscated}--" - - episodes: - end: "{aqua}-------- Konec epizody {0} --------" - endForced: "{aqua}-------- Konec epizody 0} [vynuceno hracem {1}] --------" - - scoreboard: - episode: "{gray}Epizoda {white}{0}" - players: "{white}{0}{gray} hracu" - teams: "{white}{0}{gray} tymu" - timer: "{white}{0}{gray}:{white}{1}" - timerWithHours: "{0}{gray}:{white}{1}{gray}:{white}{2}" - - motd: - beforeStart: "Ceka se na hrace..." - starting: "Probiha start hry..." - runningSolo: "Hra bezi! {0} hracu je nazivu." - runningTeams: "Hra bezi! {0} hracu v {1} tymech je nazivu." - finishedSolo: "Hra skoncila, gratulujeme hraci {0} k jeho vitezstvi!" - finishedTeams: "Hra skoncila, zapas vyhral tym {0}!" - - death: - kickMessage: "ayayay" - banMessage: "Zemrel jsi!" - teamHasFallen: "{0}Tym {1} byl vyrazen ze hry!" - - canRespawn: "{darkpurple}{obfuscated}----{lightpurple}{italic} MUZES SE RESPAWNOUT{lightpurple}, jen klikni na {italic}Respawn {lightpurple}na dalsi obrazovce." - - craft: - goldenApple: - loreLine1Player: "Vyrobeno z hlavy padleho" - loreLine2Player: "hrace {0}" - loreLine1Monster: "Vyrobeno z hlavy" - loreLine2Monster: "zhoubne prisery" - - nameGoldenAppleFromHeadNormal: "{aqua}Zlate jablko" - nameGoldenAppleFromHeadNotch: "{lightpurple}Zlata hlava" - - compass: - noRottenFlesh: "{gray}{italic}Nemas zadne shnile maso (rotten flesh)." - nothingFound: "{gray}{italic}Tva zadost zmizela v tichu." - success: "{gray}Kompas nyni ukazuje smer k nejblizsimu hraci." - - dynmap: - markerLabelDeath: "Zde zemrel hrac {0}" - markerLabelSpawn: "Zde se spawnul tym {0}" - markerLabelSpawnNoTeam: "Zde se spawnul hrac {0}" - - wall: - startGen: "{cst}Generuji hranice mapy..." - consoleDefaultWorld: "{ci}Z konzole generuji hranice teto mapy, {0}" - error: "{ce}Plugin nebyl schopny vygenerovat hranici mapy, vice informaci v logu. Pravdepodobnou pricinou je neplatnost nastavenych bloku." - unknownError: "{ce}Vyskytla se chyba, vice informaci naleznete v konzoli." - blocksError: "Plugin nebyl schopny vygenerovat hranici mapy, nastavene bloky jsou pravdepodobne neplatne." - done: "{cst}Generace byla dokoncena." - - spawns: - NaN: "{ce}To neni cislo!" - syntaxError: "{ce}Chyba v syntaxi prikazu, zkuste /uh spawns." - errorCoords: "{ce}Musite urcit souradnice z konzole." - error2Coords: "{ce}Musite urcit obe souradnice." - - add: - added: "{cs}Spawn byl pridan ve svete {0}: {1};{2}" - outOfLimits: "{ce}Nemuzete pridat spawn point za hranicemi mapy." - noSafeSpot: "{ce}Operace selhala: zadne bezpecne misto v Netheru nebylo nalezeno." - - assumptions: - solo: "{ci}Zadny tym nebyl nalezen, plugin predpoklada, ze se jedna o solo hru." - partialSolo: "{ci}Nekteri hraci nejsou soucasti zadneho tymu, jejich cislo bylo pridano do spawn poctu." - - generate: - nothingToDo: "{ci}Zazadali jste o generaci voidu, proto je tato generace prazdna." - unsupportedMethod: "{ce}Generacni metoda '{0}' neni (zatim?) podporovana." - unknownWorld: "{ce}Svet {0} neexistuje." - success: "{cs}Zazadane spawn points byly uspesne vytvoreny." - impossible: "{ce}Chcete nemozne: zazadali jste moc spawn points na male plose. Snizte pocet spawn points nebo minimalni vzdalenost mezi nimi." - - list: - nothing: "{ce}Neni zadny registrovany spawn point." - count: "{ci}Nyni je registrovano {0} spawn points." - world: "{lightpurple}Svet {0}" - item: - overworld: "{green}{0}{darkgreen};{green}{1}" - nether: "{red}{0}{darkred};{red}{1}" - end: "{yellow}{0}{gold};{yellow}{1}" - other: "{gray}{0}{darkgray};{gray}{1}" - - remove: - removed: "{cs}Spawn point {1};{2} ve svete {0} byl odstranen." - - reset: "{cs}Vsechny spawn points byly odstraneny." - - team: - syntaxError: "{ce}Chyba v syntaxi prikazu, zkuste /uh team." - unknownCommand: "{ce}Neplatny prikaz. Napiste /uh team pro vypsani seznamu dostupnych prikazu." - onlyAsAPlayer: "{ce}Tento prikaz muze byt timto zpusobem proveden pouze hracem." - - add: - errorColor: "{ce}Nepovedlo se pridat tym, zkontrolujte jmeno barvy. Tip: pouzijte Tab pro automaticke dokonceni." - errorExists: "{ce}Tento tym jiz existuje." - added: "{cs}Tym {0}{cs} byl pridan." - - remove: - doesNotExists: "{ce}Tento tym neexistuje." - removed: "{cs}Tym {0} byl odstranen." - - addplayer: - disconnected: "{ce}Nepovedlo se pridat hrace {0} do tymu {1}. Hrac musi byt pripojen k serveru." - success: "{cs}Hrac {0} byl uspesne pridan do tymu {1}" - added: "{aqua}Nyni jsi v tymu {0}{aqua}." - doesNotExists: "{ce}Takovy tym neexistuje." - full: "{ce}Tym {0}{ce} je plny!" - - joinhelp: "{ce}Pouziti: {cc}/join [hrac] <tym>{ce}." - - removeplayer: - disconnected: "{ce}Hrac {0} je odpojen od serveru!" - success: "{cs}Hrac {0} byl uspesne odstranen ze sveho tymu." - removed: "{darkaqua}Nadale nejsi v tymu {0}{darkaqua}." - - list: - nothing: "{ce}Nejsou zadne definovane tymy." - - itemTeam: "{0} ({1} hracu)" - - bulletPlayerOnline: "{green} • " - bulletPlayerOffline: "{red} • " - - itemPlayer: "{0}" - - gui: - choose: "{gold}Pokud se chcete pripojit do tymu, kliknete na jeho jmeno" - playersCount: "{gray}[{white}{0}{gray}/{white}{1}{gray}]" - playersCountUnlimited: "{gray}[{white}{0}{gray}]" - tooltipCount: "{0} hracu v tomto tymu" - tooltipJoin: "Kliknete sem, pokud se chcete pripojit do tymu {0}" - tooltipJoinInside: "Nyni jsi v tymu {0}" - leaveTeam: "{darkred}[\u00D7] {red}Kliknete sem, pokud chcete opustit svuj tym" - howToDisplayAgain: "{gray}Pokud tuto zpravu chcete zobrazit znovu, napiste /join" - noTeams: "{ce}Neni zadny dostupny tym." - - reset: - success: "{cs}Vsechny tymy byly odstraneny." - - message: - noConsole: "{ce}Nemuzes odeslat tymovou zpravu z konzole." - noTeam: "{ce}Nejsi v zadnem tymu!" - usage: "{ce}Pouziti: /{0} <zprava>" - - notAllowed: - self: "{ce}Nemas povoleni poslat soukromou zpravu svemu tymu." - others: "{ce}Nemas povoleni vstoupit do soukromeho chatu jineho tymu." - - toggle: - nowTeamChat: "{cs}Nyni pises do tymoveho chatu." - nowGlobalChat: "{cs}Nyni pises do globalniho chatu." - - nowOtherTeamChat: "{cs}Nyni pises do chatu s tymem {0}{cs}." - unknownTeam: "{ce}Takovy tym neexistuje." - - format: "{gold}[{0}{gold} svemu tymu] {reset}{1}" - formatOtherTeam: "{gold}[{0}{gold} tymu {1}{gold}] {reset}{2}" - - infos: - notStarted: "{ci}Hra jeste nezacala." - players: "{ci}{0} hracu nazivu v {1} tymech." - - bulletOnline: "{green} • " - bulletOffline: "{red} • " - - separatorAliveState: "{gray} - " - - dead: "{red}mrtvych" - alive: "{green}nazivu" - - tooltips: - online: "Prave online" - offline: "Prave offline" - - team: "Tym: {0}" - - health: "{0} pulsrdicek" - - shift: - consoleName: "konzole" - cantNotStarted: "{ce}Neni mozne posunout soucasnou epizodu, protoze hra jeste nezacala." - - heal: - usage: "{ce}Pouziti: /uh heal <hrac> [half-hearts = 20]" - offline: "{ce}Tento hrac je offline." - errorNaN: "{ce}Hej, tohle neni pocet pulsrdicek. Tohle je text. Pfff." - errorNoKill: "{ce}Kvuli predejiti preklepu neni mozne zabit hrace timto prikazem." - errorHealthNotUpdatedNoKill: "{ce}Zdravi hrace {0} nebylo updatovano, aby se predeslo zabiti." - allErrorNoKill: "{ce}Seriovy vrahu!" - - feed: - usage: "{ce}Pouziti: /uh feed <hrac> [foodPoints = 20] [saturation = max]" - offline: "{ce}Tento hrac je offline." - errorNaN: "{ce}Mnozstvi jidla (foodPoints) i saturace musi byt cisla (saturace je desetinne cislo)!" - - kill: - usage: "{ce}Pouziti: /uh kill <hrac>" - neverPlayed: "{ce}Tento hrac nikdy nenavstivil tento server." - notAlive: "{ce}{0} neni zivy hrac." - killed: "{cs}Hrac {0} je nyni prohlasen za mrtveho." - - resurrect: - usage: "{ce}Pouziti: /uh resurrect <hrac>" - unknownOrDead: "{ce}Tento hrace nehraje nebo neni mrtvy!" - offlineOk: "{cs}Protoze hrace {0} je offline, bude vzkristen po pripojeni. Pripadny ban byl odstranen." - notDead: "{ce}{0} neni mrtvy!" - broadcastMessage: "{gold}{0} se navratil ze zahrobi!" - - tpback: - usage: "{ce}Pouziti: /uh tpback <hrac> [force]" - offline: "{ce}Hrac {0} neni online." - noDeathLocation: "{ce}Nebylo nalezeno misto umrti hrace {0}." - teleported: "{cs}Hrac {0} byl uspesne teleportovan zpet." - notTeleportedNoSafeSpot: "{ce}Hrac {0} NEBYL teleportovan, protoze nebylo nalezeno zadne bezpecne misto." - notTeleportedNoSafeSpotCmd: "{ci}Pouzijte {cc}/uh tpback {0} force{ci} pro teleport i pres nenalezeni bezpecneho mista." - - tp: - NaN: "{ce}Souradnice se musi skladat ze tri cisel." - targetOffline: "{ce}{0} je offline!" - teamDoesNotExists: "{ce}Takovy tym neexistuje." - - spectators: - syntaxError: "{ce}Chyba v syntaxi prikazu, zkuste /uh spec." - unknownCommand: "{ce}Neplatny prikaz. Napiste /uh spec pro seznam dostupnych prikazu." - offline: "{ce}Hrac {0} neni online." - - add: - success: "{cs}Hrac {0} je nyni spectatorem." - - remove: - success: "{cs}Hrac {0} je nyni hracem." - - list: - nothing: "{ce}Neni mozne vypsat spectatory, jelikoz zadni neexistuji." - countSpectators: "{ci}{0} registrovanych spectatoru." - countOnlyInitial: "{ci}Tento seznam zahrnuje pouze pocatecni spectatory." - itemSpec: "{lightpurple} - {0}" - - freeze: - frozen: "{cst}Byl jsi zmrazen administratorem {0}." - unfrozen: "{cst}Byl jsi odmrazen administratorem {0}." - - playerFrozen: "{cs}{0} je nyni zmrazen." - playerUnfrozen: "{cs}{0} je nyni odmrazen." - - playerOnly: "{ce}Abys mohl napsat tento prikaz timto zpusobem, musis byt hrac." - offline: "{ce}{0} je offline!" - - scoreboard: "{darkaqua}Hra pozastavena" - - broadcast: - globalFreeze: "{darkaqua}Cela hra je nyni pozastavena." - globalUnfreeze: "{darkaqua}Hra opet bezi." - - borders: - syntaxError: "{ce}Chybe v syntaxi, napiste /uh border." - NaN: "{ce}'{0}' neni cislo." - - current: - messageSquared: "{ci}Soucasna velikost mapy je {0}*{0}." - messageCircular: "{ci}Soucasny prumer mapy je {0} bloku." - - set: - playersOutsideCanceled: "{ce}Nekteri hraci jsou za hranici mapy; provedeni prikazu bylo zruseno." - playersOutsideCanceledCmd: "{ci}Pouzijte {cc}/uh border set {0} force{ci} pro zmenu velikosti hranic bez ohledu na tuto zpravu." - playersOutsideCanceledWarnWorldBorder: "{ce}VAROVANI: {ci}hraci za hranici mapy nebudou teleportovani, protoze WorldBorder neni nainstalovan!" - - broadcastSquared: "{lightpurple}Velikost mapy je nyni {0}*{0}." - broadcastCircular: "{lightpurple}Prumer mapy je nyni {0} bloku." - - warning: - canceled: "{cs}Varovani bylo zruseno." - - set: "{cs}Budouci velikost byla ulozena. Vsichni hraci za touto budouci hranici mapy budou varovani kazdych {0} sekund." - - messageSquared: "{ce}Nyni jsi za budouci hranici mapy, ktera bude mit velikost {0}*{0}." - messageCircular: "{ce}Nyni jsi za budouci hranici mapy (prumer {0} bloku)." - - messageDistance: "{ci}Musis ujit jeste {0} bloku, nez budes uvnitr mapy." - messageDistanceTime: "{ci}Musis ujit jeste {0} bloku, nez budes uvnitr mapy - mas na to {1} minut." - - nameTimer: "Hranice se zmensuje" - - timerUp: "{cs}Casovac do nastaveni nove velikost mapy nyni bezi!" - - check: - allPlayersInside: "{cs}Vsichni hraci jsou uvnitr dane velikosti mapy." - countPlayersOutside: "{ci}Nyni je {0} hracu za hranici dane velikosti mapy." - - itemPlayerFar: "{lightpurple} - {red}{0}{ci} (daleko od hranice)" - itemPlayerClose: "{lightpurple} - {yellow}{0}{ci} (blizko hranici)" - itemPlayerVeryClose: "{lightpurple} - {green}{0}{ci} (velmi blizko hranici)" - - timers: - syntaxError: "{ce}Chyba v syntaxi prikazu, zkuste /uh timers." - durationSyntaxError: "{ce}Chyba v casove syntaxi - funguji formaty mm, mm:ss a hh:mm:ss." - timerDoesNotExists: "{ce}Takovy casovac neexistuje." - alreadyExists: "{ce}Casovac nazvany {0}{ce} jiz existuje, prosim vyberte jine jmeno." - - added: "{cs}Casovac {0}{cs} s delkou {1} byl registrovan." - set: "{cs}Delka casovace {0}{cs} je nyni {1}." - displayed: "{cs}Casovac {0}{cs} je nyni zobrazen." - hidden: "{cs}}Casovac {0}{cs} je nyni skryt." - started: "{cs}}Casovac {0}{cs} zacal odpocitavat." - paused: "{cs}}Casovac {0}{cs} je nyni pauznut." - resumed: "{cs}}Casovac {0}{cs} nyni pokracuje." - stopped: "{cs}}Casovac {0}{cs} byl zastaven." - removed: "{cs}}Casovac {0}{cs} byl odstranen." - - list: - count: "{ci}{0} casovac(u) je registrovano." - itemRunning: "{green} • {ci}{0}{ci} - celkem {1} sekund - {2}" - itemPaused: "{yellow} • {ci}{0}{ci} - celkem {1} sekund - {2}" - itemStopped: "{red} • {ci}{0}{ci} - celkem {1} sekund" - - protips: - base: "{darkpurple}Tip pro vas!" - - teamchat: - lock: "{gray}Muzes zamykat a odemykat tymovy chat prikazem {cc}/togglechat{gray}." - useTCommand: "{gray}Muzes odeslat zpravu svemu tymu prikazem {cc}/t <message>{gray}." - useGCommand: "{gray}Muzes odeslat zpravu vsem hracum na serveru prikazem {cc}/g <message>{gray}." - - crafts: - goldenHead: "{gray}Muzes craftit zlata jablka pomoci hlav (stejny recept s hlavou misto jablka)." - compassEasy: "{gray}Kompas se da vycrafit s kosti, zkazenym masem, pavoucim okem a strelnym prachem v rozich receptu." - compassMedium: "{gray}Kompas se da vycraftit s kosti, zkazenym masem, pavoucim okem a strelnym prachem v rozich receptu + enderperlou veprostred." - compassHard: "{gray}Kompas se da vycraftit s kosti, zkazenym masem, pavoucim okem a strelnym prachem v rozich receptu + Eye of Ender veprostred." - glisteringMelon: "{gray}Glistering melon se da vycrafit z melounu a goldblocku." - noEnchGoldenApple: "{gray}V teto hre je enchantovane zlate jablko zakazano." - - start: - invincibility: "{gray}Spadl jsi na strom? Rychle seskoc, jsi nesmrtelny po dobu 25 sekund!" diff --git a/src/main/resources/i18n/en_US.po b/src/main/resources/i18n/en_US.po new file mode 100644 index 0000000..34fb00e --- /dev/null +++ b/src/main/resources/i18n/en_US.po @@ -0,0 +1,2264 @@ +# Copyright or © or Copr. Amaury Carrade (2014 - 2016) +# +# http://amaury.carrade.eu +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-12-19 16:34+0100\n" +"PO-Revision-Date: 2016-12-19 16:35+0100\n" +"Last-Translator: Amaury Carrade\n" +"Language-Team: Amaury Carrade\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n!=1;\n" +"X-Generator: Poedit 1.7.5\n" + +#. The name of the warning timer displaying the time left before the next border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:86 +msgid "Border shrinking" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:365 +msgid "{cs}All players are inside the given border." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:369 +msgid "{ci}There are {0} players outside the given border." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:375 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:379 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:383 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:429 +msgid "{red}Warning!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:429 +msgid "{white}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:431 +msgid "{red}{bold}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:432 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder; in the center, an ender pearl." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "" + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:132 +msgid "{darkpurple}ProTip!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:209 +msgid "Ultra Hardcore plugin loaded." +msgstr "" + +#. Title of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:70 +msgid "{red}Team deleted" +msgstr "" + +#. Lore of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:72 +msgid "{gray}The team {0}{gray} was deleted by another player." +msgstr "" + +#. Lore of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:75 +msgid "{gray}Press {white}Escape{gray} to go back to the teams list." +msgstr "" + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:58 +msgid "{0} » {darkred}Delete" +msgstr "" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:72 +msgid "{green}Keep this team alive" +msgstr "" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:84 +msgid "{red}Delete this team {italic}forever" +msgstr "" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:67 +msgid "{0} » {black}Members" +msgstr "" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:131 +msgid "{green}« Go back" +msgstr "" + +#. The title of a button to select a player (a skull button). {0} = player's display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:98 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:98 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:66 +msgid "Teams » {black}{0}" +msgstr "" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:79 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{white}Click with a banner {gray}to update this team's banner" +msgstr "" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:89 +msgid "{green}Update the color" +msgstr "" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:91 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:98 +msgid "{green}Rename the team" +msgstr "" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:100 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:107 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "" + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "" + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{green}Add or remove players" +msgstr "" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:122 +msgid "{red}Delete this team" +msgstr "" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:124 +msgid "{gray}Cannot be undone" +msgstr "" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:75 +msgid "{black}Select a team {reset}({0})" +msgstr "" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:87 +msgid "{white}Rename your team" +msgstr "" + +#. Warning displayed in the "Rename your team" button, if the player is not in a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{gray}You have to be in a team" +msgstr "" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:98 +msgid "{white}New team" +msgstr "" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:116 +msgid "{blue}Players" +msgstr "" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:120 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {red}This team is full" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:144 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "" + +#. Title of the team item in the teams selector GUI (with max). {0}: team display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:182 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "" + +#. Title of the team item in the teams selector GUI (without max) {0}: team display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:184 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:198 +msgid "{red}No team created" +msgstr "" + +#. Subtitle of the item displayed in the teams selector GUI if there isn't anything to display. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:201 +msgid "{gray}Click the emerald button below to create one." +msgstr "" + +#. Subtitle of the item displayed in the teams selector GUI if there isn't anything to display and the player cannot create a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:203 +msgid "{gray}Wait for an administrator to create one." +msgstr "" + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "" + +#. The title of the button opening the sign to write the team name (creator GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "" + +#. The legend of the button opening the sign to write the team name (creator GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "" + +#. The summary title in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "" + +#. The team name in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "" + +#. The team color in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "" + +#. The team members count in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:170 +msgid "{cs}Team created." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:176 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:117 +msgid "{ce}This team already exists." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:148 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:321 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:374 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:212 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:90 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:217 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "" + +#. Format of a private team message from a team member. {0} = sender display name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:100 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:106 +msgid "{ce}You are not in a team!" +msgstr "" + +#. Format of a private team message from a non-team-member. {0} = sender display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:113 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:514 +msgid "{gold}Click on the names below to join a team" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:535 +msgid "{0} ({red}dead{reset})" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:540 +msgid "{0} ({green}alive{reset})" +msgstr "" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:550 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "" + +#. Team count without max players (ex. [3]) followed in-game by the team name. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:552 +msgid "{gray}[{white}{0}{gray}]" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:554 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "" +msgstr[1] "" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:565 +#, java-format +msgid "You are in the team {0}" +msgstr "" + +#. Tooltip on the chat team selector GUI when the player is not in the team. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:567 +#, java-format +msgid "Click here to join the team {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:577 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "" + +#. No teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:621 +msgid "{gold}Your team: {0}" +msgstr "" + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:158 +msgid "jayjay" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:236 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "" + +#. A message displayed to the players under the death screen, about the respawn possibility even if the death screen says the opposite (in hardcore mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:280 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" + +#. The kick message displayed if a player tries to relog after his death and it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:385 +msgid "You are dead!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:458 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:459 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game " +"(warnings excluded)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:460 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:470 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:471 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "" + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:475 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:488 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:607 +msgid "{cs}The timer before the new border is up!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:639 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:643 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "" + +#. The title displayed when the episode change. {0} = new episode number; {1} = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:655 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "" + +#. Broadcast +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:679 +msgid "{green}--- GO ---" +msgstr "" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:687 +msgid "{darkgreen}Let's go!" +msgstr "" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:689 +msgid "{green}Good luck, and have fun" +msgstr "" + +#. All players are notified +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:821 +msgid "{gold}{0} returned from the dead!" +msgstr "" + +#. The title of the item given before the game to select a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java:110 +msgid "{green}{bold}Select a team {gray}(Right-Click)" +msgstr "" + +#. The lore of the item given before the game to select a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java:112 +msgid "{gray}Right-click to select your team for this game" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:285 +msgid "{aqua}Golden head" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:202 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:286 +msgid "{lightpurple}Golden head" +msgstr "" + +#. Error message if a player tries to use his pointing compass without rotten flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:305 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "" + +#. Error message if a player tries to use his pointing compass without a player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:336 +msgid "{gray}{italic}Only silence answers your request." +msgstr "" + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:343 +msgid "{gray}The compass now points to the closest player." +msgstr "" + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:153 +#, java-format +msgid "Death point of {0}" +msgstr "" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:232 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:237 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:294 +#, java-format +msgid "Spawn point of {0}" +msgstr "" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:280 +msgid "Made from the fallen head of a malignant monster" +msgstr "" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:388 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:394 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:421 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:427 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:140 +msgid "{gray}Episode {white}{0}" +msgstr "" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:158 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "" +msgstr[1] "" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:162 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "" +msgstr[1] "" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:207 +msgid "{bold}Your team" +msgstr "" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:280 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "" +msgstr[1] "" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:311 +msgid "{blue}{bold}Border" +msgstr "" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:319 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "" +msgstr[1] "" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:322 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "" +msgstr[1] "" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:338 +msgid "{white}{0} {1}" +msgstr "" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}X: {white}{0} {1}" +msgstr "" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:345 +msgid "{gray}Z: {white}{0} {1}" +msgstr "" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:386 +msgid "{darkaqua}Game frozen" +msgstr "" + +#. Default nick name when a player cannot be recognized. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/SidebarPlayerCache.java:133 +msgid "Unknown" +msgstr "" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:120 +msgid "{red}{bold}Rules and informations" +msgstr "" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:131 +msgid "{darkgray}- {reset}{0}" +msgstr "" + +#. Episode in the player list ({episodeText} replacement). {0} = current episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:115 +#, java-format +msgid "Episode {0}" +msgstr "" + +#. Players in the player list ({playersText} replacement). {0} = current alive players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "" +msgstr[1] "" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} team" +msgid_plural "{0} teams" +msgstr[0] "" +msgstr[1] "" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:90 +msgid "Waiting for players..." +msgstr "" + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:99 +msgid "Starting in progress..." +msgstr "" + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:114 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "" +msgstr[1] "" + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive count. Plural based on players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:119 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "" +msgstr[1] "" + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:136 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:141 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:108 +msgid "{ce}Usage: /{0} <message>" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "" + +#. Translation +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:73 +msgid "{cs}Warning canceled." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:88 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:118 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:118 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "" + +#. Some players are outside +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:113 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:117 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:147 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "" + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "" + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "" + +#. /uh spawns add <x>: Two coordinates needed! +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "" + +#. Solo mode? +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "" + +#. A spawn point in the /uh spawns list command (in the overworld) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:130 +msgid "{green}{0}{darkgreen};{green}{1}" +msgstr "" + +#. A spawn point in the /uh spawns list command (in the Nether) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:134 +msgid "{red}{0}{darkred};{red}{1}" +msgstr "" + +#. A spawn point in the /uh spawns list command (in the End) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:138 +msgid "{yellow}{0}{gold};{yellow}{1}" +msgstr "" + +#. A spawn point in the /uh spawns list command (in a custom world) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:142 +msgid "{gray}{0}{darkgray};{gray}{1}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:185 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +msgid "{ce}The player {0} is not online." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his " +"spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "" + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:117 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:100 +msgid "{ce}Unable to retrieve the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:134 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:103 +msgid "" +"{ce}In offline mode, you cannot add players if they never came to this " +"server." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:143 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:190 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:121 +msgid "{cs}Team {0}{cs} added." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:163 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:92 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:109 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:143 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "" +msgstr[1] "" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:74 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:77 +msgid "{ce}Either this team does not exists, or you are not in a team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:78 +msgid "{ce}You must run this command with a banner in your main hand." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:83 +msgid "{cs}The banner of the team {0}{cs} was successfully updated." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:109 +msgid "" +"{cc}/uh team banner [team name ...] {ci}: updates the team's banner using " +"the banner in the sender hand. If the team name is not provided, uses the " +"sender's team." +msgstr "" + +#. Error message of /uh team bannerreset from the console without name +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:71 +msgid "{ce}From the console, you must provide a team name." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:82 +msgid "" +"{cs}The banner of the team {0}{cs} was successfully reset to the default one." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:108 +msgid "" +"{cc}/uh team bannerreset [team name ...] {ci}: resets the banner of the team " +"to the default. If the team name is not provided, uses the sender's team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:110 +msgid "{aqua}------ Team commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:111 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the " +"given team. Without arguments, displays the chat-based team selector." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:112 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:119 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the " +"config are probably invalid." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:82 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:92 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:123 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard. " +"Automatic when a timer is started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or hh:mm:" +"ss." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:61 +msgid "{ce}You cannot load unknown players in offline mode, sorry." +msgstr "" + +#. Error returned if one calls /uh loadplayers without arguments. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:68 +msgid "{ce}You need to provide at least one player name." +msgstr "" + +#. Message displayed when the /uh loadplayers command is used, as the execution may take some time. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:73 +msgid "{cst}Loading players..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:80 +msgid "{cs}Loaded {0} player successfully." +msgid_plural "{cs}Loaded {0} players successfully." +msgstr[0] "" +msgstr[1] "" + +#. Message sent if some players cannot be loaded while /uh loadplayers is used. 0 = amount of players missing; 1 = list of nicknames (format "nick1, nick2, nick3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:88 +msgid "{ce}{0} player is missing: {1}." +msgid_plural "{ce}{0} players are missing: {1}." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:108 +msgid "" +"{cc}/uh loadplayers <pseudo> [pseudo] ... {ci}: loads the given players in " +"the server so they can be added to teams even if they never logged in." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if " +"the entire game is frozen." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this " +"in order to relaunch the timer." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:99 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the " +"game." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:133 +msgid "{aqua}------ Beginning of the game ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:134 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:135 +msgid "{aqua}Startup options" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:136 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append " +"them to the command with spaces." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:137 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:138 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:145 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:109 +msgid "{cs}The player {0} is now a spectator." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ce}The player {0} was not found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgid "{cs}The player {0} is now a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:144 +msgid "{ce}There isn't any spectator to list." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:148 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:149 +msgid "{ci}This count includes only the initial spectators." +msgstr "" + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:154 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:191 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:193 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:194 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:195 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:203 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed ..." +">{ci}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +msgid "{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "" +msgstr[1] "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:334 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:335 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:338 +msgid "Or" +msgstr "" + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:341 +msgid "click here" +msgstr "" + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:347 +msgid "to generate the spawns randomly." +msgstr "" + +#. A simple information, because this start is slower (yeah, Captain Obvious here) +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:479 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "" + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:514 +msgid "{gray}Player {0}{gray} teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:573 +msgid "{cs}All teams are teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:574 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:575 +msgid "Click here to start the game" +msgstr "" + +#. Displayed in the action bar when the slow teleportation is finished but the game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:584 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:615 +msgid "{ce}Please execute {cc}/uh start slow:true{ce} before." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:621 +msgid "{ce}Please wait while the players are teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:717 +msgid "" +"{red}{bold}Warning!{white} The grace period ended, you are now vulnerable." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:736 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "" + +#. Spectators list item if the nick cannot be found +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1073 +#, java-format +msgid "Unknown player with UUID {0}" +msgstr "" + +#. The "and" in the winners players list (like "player1, player2 and player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1219 +msgctxt "winners_list" +msgid "and" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1231 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1235 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "" + +#. The main title of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1247 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1254 +msgid "{darkgreen}{0}" +msgstr "" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1249 +msgid "{green}This team wins the game!" +msgstr "" + +#. The subtitle of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1256 +msgid "{green}wins the game!" +msgstr "" diff --git a/src/main/resources/i18n/en_US.yml b/src/main/resources/i18n/en_US.yml deleted file mode 100644 index 8dea450..0000000 --- a/src/main/resources/i18n/en_US.yml +++ /dev/null @@ -1,507 +0,0 @@ -author: "Amaury Carrade" -keys: - load: - spawnPointAdded: "Spawn point {0},{1} added from the config file" - invalidSpawnPoint: "Invalid spawn point set in config: {0}" - teamAdded: "Team {0} added from the config file" - namedTeamAdded: "Team {0} ({1}) added from the config file" - invalidTeam: "Invalid team set in config: {0}" - recipeApple: "Added new recipes for golden apple." - recipeCompass: "Added new recipe for compass." - recipeMelon: "Added new recipe for golden melon." - loaded: "Ultra Hardcore plugin loaded." - - WBNotInstalled1: "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" - WBNotInstalled2: "{gray}Also, without WorldBorder, the border can't be reduced during the game (warnings excluded)." - WBNotInstalled3: "{gray}Just install the plugin; UHPlugin will automatically configure it." - - SPNotInstalled1: "{darkred}[UHC] {ce}SpectatorPlus is not installed." - SPNotInstalled2: "{gray}If you want a spectator mode, install the plugin; UHPlugin will configure it automatically." - - PLNotInstalled1: "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" - PLNotInstalled2: "{gray}The following options require the presence of ProtocolLib:" - PLNotInstalledItem: "{darkgray} - {gray}{0}" - PLNotInstalled3: "{gray}ProtocolLib is available here: {0}" - - cmd: - errorLoad: "{ce}An error occurred, see console for details. This is probably a bug." - errorUnknown: "{ce}This subcommand does not exists. See /uh for the available commands." - errorUnauthorized: "{ce}You are not allowed to execute this command." - - titleHelp: "{yellow}{0} - version {1}" - legendHelp: "{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed ...>{ci}." - helpNextPage: "{gray}Next page: /uh {0}" - - titleGameCmd: "{aqua}------ Game-related commands ------" - helpStart: "{cc}/uh start {ci}: launches the game." - helpStartSlow: "{cc}/uh start slow {ci}: launches the game slowly, in two steps, for smaller servers." - helpShift: "{cc}/uh shift {ci}: shifts an episode." - helpTeam: "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." - helpSpawns: "{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for details." - helpSpec: "{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." - helpWall: "{cc}/uh generatewalls {ci}: generates the walls according to the configuration." - helpBorder: "{cc}/uh border {ci}: manages borders. Execute /uh border for details." - - titleBugCmd: "{aqua}------ Bugs-related commands ------" - helpHeal: "{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the number of half-hearts provided (default 20)." - helpHealall: "{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of only one." - helpFeed: "{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." - helpFeedall: "{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." - helpKill: "{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." - helpResurrect: "{cc}/uh resurrect <player> {ci}: resurrects a player." - helpTpback: "{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his death location." - - titleMiscCmd: "{aqua}------ Miscellaneous commands ------" - helpFreeze: "{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh freeze for details." - helpFinish: "{cc}/uh finish {ci}: displays the name of the winner(s) and launches some fireworks." - helpTP: "{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for details." - helpTimers: "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." - helpInfos: "{cc}/uh infos {ci}: prints some infos about the current game." - helpAbout: "{cc}/uh about {ci}: informations about the plugin and the translation." - - teamHelpTitle: "{aqua}------ Team commands ------" - teamHelpAdd: "{cc}/uh team add <color> {ci}: adds a team with the provided color." - teamHelpAddName: "{cc}/uh team add <color> <name ...> {ci}: adds a named team with the provided name and color." - teamHelpRemove: "{cc}/uh team remove <name ...> {ci}: removes a team" - teamHelpJoin: "{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the given team. The name of the team is it color, or the explicit name given." - teamHelpLeave: "{cc}/uh team leave <player> {ci}: removes a player from his team." - teamHelpList: "{cc}/uh team list {ci}: lists the teams and their players." - teamHelpReset: "{cc}/uh team reset {ci}: removes all teams." - teamHelpJoinCmd: "{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the given team. Without arguments, displays the chat-based team selector." - teamHelpLeaveCmd: "{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." - - spawnsHelpTitle: "{aqua}------ Spawns points commands ------" - spawnsHelpAdd: "{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the current location of the sender." - spawnsHelpAddXZ: "{cc}/uh spawns add <x> <z> {ci}: adds a spawn point for a team or a player, at the provided coordinates, in the default world." - spawnsHelpGenerate: "{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh spawns generate for details." - spawnsHelpGenerateDetailsCmdTitle: "{aqua}Command" - spawnsHelpGenerateDetailsCmd: "{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] [xCenter] [zCenter] [world]" - spawnsHelpGenerateDetailsShapesTitle: "{aqua}Shapes" - spawnsHelpGenerateDetailsShapesRandom: " - {cc}random{ci}: generates random spawn points on the map, with a minimal distance between them." - spawnsHelpGenerateDetailsShapesGrid: " - {cc}grid{ci}: generates the spawn points on concentric squares, with a constant distance between two generated points." - spawnsHelpGenerateDetailsShapesCircular: " - {cc}circular{ci}: generates the spawn points on concentric circles, with a minimal distance between two generated points. In each circle, the angle (and the distance) between two spawn points is constant." - spawnsHelpGenerateDetailsArgsTitle: "{aqua}Arguments" - spawnsHelpGenerateDetailsArgsSize: " - {cc}size{ci}: the size of the region where the spawn points will be generated. Squared or circular, following the shape of the map. Default: map' size." - spawnsHelpGenerateDetailsArgsDistanceMin: " - {cc}distanceMin{ci}: the minimal distance between two spawn points. Default: 250 blocks." - spawnsHelpGenerateDetailsArgsCount: " - {cc}count{ci}: the number of spawn points to generate. Default: the number of players or teams." - spawnsHelpGenerateDetailsArgsCenter: " - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the points are generated. Default: world' spawn point." - spawnsHelpGenerateDetailsArgsWorld: " - {cc}world{ci}: the world where the spawn points will be generated." - spawnsHelpList: "{cc}/uh spawns list {ci}: lists the registered spawn points." - spawnsHelpDump: "{cc}/uh spawns dump {ci}: displays the registered spawn points in an exportable format. {gray}Use this to plot the spawn points, as example." - spawnsHelpRemove: "{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the specified coordinates, or at the current location if the sender without coordinates." - spawnsHelpReset: "{cc}/uh spawns reset {ci}: removes all registered spawn points." - - specHelpTitle: "{aqua}------ Startup spectators commands ------" - specHelpNoticeSpectatorPlusNotInstalled: "{ce}Please note{ci}: because SpectatorPlus is not present, a spectator is {italic}only{ci} an ignored player." - specHelpAdd: "{cc}/uh spec add <player>{ci}: adds a startup spectator." - specHelpRemove: "{cc}/uh spec remove <player>{ci}: removes a startup spectator." - specHelpList: "{cc}/uh spec list{ci}: lists the startup spectators." - - freezeHelpTitle: "{aqua}------ Freeze commands ------" - freezeHelpOn: "{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a specified player." - freezeHelpOff: "{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if the entire game is frozen." - freezeHelpAll: "{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." - freezeHelpNone: "{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this in order to relaunch the timer." - - borderHelpTitle: "{aqua}------ Border commands ------" - borderHelpCurrent: "{cc}/uh border current{ci}: returns the current size of the map." - borderHelpSet: "{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If force is not given, the operation will be canceled if there is a player outside the border." - borderHelpWarning: "{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns all players outside the given future diameter. It's just a notice, nothing else." - borderHelpWarningCancel: "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." - borderHelpCheck: "{cc}/uh border check <diameter>{ci}: returns a list of the players outside the given border size." - - tpHelpTitle: "{aqua}------ Teleportation commands ------" - tpHelpTeam: "{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team to the given location/target." - tpHelpSpectators: "{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators (aka non-alive players) to the given location/target." - - timersHelpTitle: "{aqua}------ Timers commands ------" - timersHelpAdd: "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." - timersHelpSet: "{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a timer." - timersHelpDisplay: "{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard. Automatic when a timer is started." - timersHelpHide: "{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. Don't stops the timer." - timersHelpStart: "{cc}/uh timers start <title ...> {ci}: starts a timer." - timersHelpPause: "{cc}/uh timers pause <title ...> {ci}: pauses a timer." - timersHelpResume: "{cc}/uh timers resume <title ...> {ci}: resumes a timer." - timersHelpStop: "{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be removed from the scoreboard." - timersHelpRemove: "{cc}/uh timers remove <title ...> {ci}: deletes a timer." - timersHelpList: "{cc}/uh timers list {ci}: lists the registered timers." - timersHelpDurations: "{gray}Durations' format : mm, mm:ss or hh:mm:ss." - - about: - authors: "Plugin made with love by {0}." - and: "and" - - build: - number: "Build number: {0}." - notAvailable: "Build number not available." - - i18n: - title: "{aqua}------ Translations ------" - selected: "Current language: {0} (translated by {1})." - fallback: "Fallback language: {0} (translated by {1})." - license: - title: "{aqua}------ License ------" - license: "Published under the GNU General Public License (version 3)." - - start: - already: "{ce}The game is already started! Reload or restart the server to restart the game." - syntax: "{ce}Syntax error. Usage: /uh start [slow] or /uh start slow go." - notEnoughTP: "{ce}Unable to start the game: not enough teleportation spots." - teleportationInProgress: "{lightpurple}Teleportation in progress... Please wait." - - startSlowBeforeStartSlowGo: "{ce}Please execute {cc}/uh start slow{ce} before." - startSlowWaitBeforeGo: "{ce}Please wait while the players are teleported." - startSlowTeamTP: "{gray}Team {0}{gray} teleported." - startSlowAllTeamsTP: "{cs}All teams are teleported." - startSlowAllTeamsTPCmd: "{gray}Use {cc}/uh start slow go{gray} to start the game." - - go: "{green}--- GO ---" - - finish: - notStarted: "{ce}The game is not started!" - notFinished: "{ce}There's not one team alive!" - - and: "and" - - broadcast: - withTeams: "{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) for their victory! {darkgreen}{obfuscated}--" - withoutTeams: "{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! {darkgreen}{obfuscated}--" - - episodes: - end: "{aqua}-------- End of episode {0} --------" - endForced: "{aqua}-------- End of episode {0} [forced by {1}] --------" - - scoreboard: - episode: "{gray}Episode {white}{0}" - players: "{white}{0}{gray} players" - teams: "{white}{0}{gray} teams" - timer: "{white}{0}{gray}:{white}{1}" - timerWithHours: "{0}{gray}:{white}{1}{gray}:{white}{2}" - - motd: - beforeStart: "Waiting for players..." - starting: "Starting in progress..." - runningSolo: "Game running! {0} players alive." - runningTeams: "Game running! {0} players alive in {1} teams." - finishedSolo: "Game finished; congratulation to {0} for his victory!" - finishedTeams: "Game finished; the team {0} win this match!" - - death: - kickMessage: "jayjay" - banMessage: "You are dead!" - teamHasFallen: "{0}The team {1} has fallen!" - - canRespawn: "{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next screen." - - craft: - goldenApple: - loreLine1Player: "Made from the fallen head" - loreLine2Player: "of {0}" - loreLine1Monster: "Made from the fallen head" - loreLine2Monster: "of a malignant monster" - - nameGoldenAppleFromHeadNormal: "{aqua}Golden head" - nameGoldenAppleFromHeadNotch: "{lightpurple}Golden head" - - compass: - noRottenFlesh: "{gray}{italic}You do not have rotten flesh." - nothingFound: "{gray}{italic}Only silence answers your request." - success: "{gray}The compass now points to the closest player." - - dynmap: - markerLabelDeath: "Death point of {0}" - markerLabelSpawn: "Spawn point of the team {0}" - markerLabelSpawnNoTeam: "Spawn point of {0}" - - wall: - startGen: "{cst}Generating the walls..." - consoleDefaultWorld: "{ci}From the console, generating the walls of the default world, {0}" - error: "{ce}Unable to generate the wall: see logs for details. The blocks set in the config are probably invalid." - unknownError: "{ce}An error occurred, see console for details." - blocksError: "Unable to build the wall, the blocks set in the config file are invalid." - done: "{cst}Generation done." - - spawns: - NaN: "{ce}This is not a number!" - syntaxError: "{ce}Syntax error; see /uh spawns." - errorCoords: "{ce}You need to specify the coordinates from the console." - error2Coords: "{ce}You need to specify two coordinates." - - add: - added: "{cs}Spawn added in the world {0}: {1};{2}" - outOfLimits: "{ce}You cannot add a spawn point out of the borders." - noSafeSpot: "{ce}Unable to add this spawn point: no safe spot found in the Nether." - - assumptions: - solo: "{ci}No team found: assuming the game is a solo game." - partialSolo: "{ci}Some players are not in a team; their number was added to the spawn count." - - generate: - nothingToDo: "{ci}You asked a void generation. Thus, the generation is empty." - unsupportedMethod: "{ce}The generation method “{0}” is not (yet?) supported." - unknownWorld: "{ce}The world {0} doesn't exists." - success: "{cs}Successfully generated the asked spawn points." - impossible: "{ce}You asked for the impossible: there are too many spawn points on a too small surface. Decrease the spawn count or the minimal distance between two points." - - list: - nothing: "{ce}There isn't any registered spawn point." - count: "{ci}There are {0} registered spawn points." - world: "{lightpurple}World {0}" - item: - overworld: "{green}{0}{darkgreen};{green}{1}" - nether: "{red}{0}{darkred};{red}{1}" - end: "{yellow}{0}{gold};{yellow}{1}" - other: "{gray}{0}{darkgray};{gray}{1}" - - remove: - removed: "{cs}The spawn point {1};{2} in the world {0} was removed." - - reset: "{cs}All the spawn points were removed." - - team: - syntaxError: "{ce}Syntax error, see /uh team." - unknownCommand: "{ce}Unknown command. See /uh team for available commands." - onlyAsAPlayer: "{ce}This command can only be executed this way as a player." - - add: - errorColor: "{ce}Unable to add the team, check the color name. Tip: use Tab to autocomplete." - errorExists: "{ce}This team already exists." - added: "{cs}Team {0}{cs} added." - - remove: - doesNotExists: "{ce}This team does not exists." - removed: "{cs}Team {0} deleted." - - addplayer: - disconnected: "{ce}Unable to add the player {0} to the team {1}. This player is unknown in the server." - success: "{cs}The player {0} was successfully added to the team {1}" - added: "{aqua}You are now in the {0}{aqua} team." - doesNotExists: "{ce}This team does not exists." - full: "{ce}The team {0}{ce} is full!" - - joinhelp: "{ce}Usage: {cc}/join [player] <team>{ce}." - - removeplayer: - disconnected: "{ce}The player {0} is disconnected and never logged in before!" - success: "{cs}The player {0} was successfully removed from his team." - removed: "{darkaqua}You are no longer part of the {0}{darkaqua} team." - - list: - nothing: "{ce}There isn't any team to show." - - itemTeam: "{0} ({1} players)" - - bulletPlayerOnline: "{green} • " - bulletPlayerOffline: "{red} • " - - itemPlayer: "{0}" - - gui: - choose: "{gold}Click on the names below to join a team" - playersCount: "{gray}[{white}{0}{gray}/{white}{1}{gray}]" - playersCountUnlimited: "{gray}[{white}{0}{gray}]" - tooltipCount: "{0} player(s) in this team" - tooltipJoin: "Click here to join the team {0}" - tooltipJoinInside: "You are in the team {0}" - leaveTeam: "{darkred}[\u00D7] {red}Click here to leave your team" - howToDisplayAgain: "{gray}Run /join to display this again" - noTeams: "{ce}There isn't any team available." - - reset: - success: "{cs}All teams where removed." - - message: - noConsole: "{ce}You can't send a team-message from the console." - noTeam: "{ce}You are not in a team!" - usage: "{ce}Usage: /{0} <message>" - - notAllowed: - self: "{ce}You are not allowed to send a private message to your team." - others: "{ce}You are not allowed to enter in the private chat of another team." - - toggle: - nowTeamChat: "{cs}You are now chatting with your team only." - nowGlobalChat: "{cs}You are now chatting with everyone." - - nowOtherTeamChat: "{cs}You are now chatting with the team {0}{cs}." - unknownTeam: "{ce}This team does not exists." - - format: "{gold}[{0}{gold} -> his team] {reset}{1}" - formatOtherTeam: "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" - - infos: - notStarted: "{ci}The game is not started." - players: "{ci}{0} players alive in {1} teams." - - bulletOnline: "{green} • " - bulletOffline: "{red} • " - - separatorAliveState: "{gray} - " - - dead: "{red}dead" - alive: "{green}alive" - - tooltips: - online: "Currently online" - offline: "Currently offline" - - team: "Team: {0}" - - health: "{0} half-hearts" - - shift: - consoleName: "the console" - cantNotStarted: "{ce}You can't shift the current episode because the game is not started." - - heal: - usage: "{ce}Usage: /uh heal <player> [number of half-hearts = 20]" - offline: "{ce}This player is offline." - errorNaN: "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." - errorNoKill: "{ce}You can't kill a player with this command, to avoid typo fails." - errorHealthNotUpdatedNoKill: "{ce}The health of {0} was not updated to avoid a kill." - allErrorNoKill: "{ce}Serial killer!" - - feed: - usage: "{ce}Usage: /uh feed <player> [foodPoints = 20] [saturation = max]" - offline: "{ce}This player is offline." - errorNaN: "{ce}Food points and saturation must be numbers (floats for the saturation)!" - - kill: - usage: "{ce}Usage : /uh kill <player>" - neverPlayed: "{ce}This player was never seen on this server." - notAlive: "{ce}{0} is not an alive player." - killed: "{cs}The player {0} is now marked as dead." - - resurrect: - usage: "{ce}Usage: /uh resurrect <player>" - unknownOrDead: "{ce}This player is not playing or dead!" - offlineOk: "{cs}Because {0} is offline, he will be resurrected when he logins. If he was, he is no longer banned." - notDead: "{ce}{0} is not dead!" - broadcastMessage: "{gold}{0} returned from the dead!" - - tpback: - usage: "{ce}Usage: /uh tpback <player> [force]" - offline: "{ce}The player {0} is not online." - noDeathLocation: "{ce}No death location available for the player {0}." - teleported: "{cs}The player {0} was teleported back." - notTeleportedNoSafeSpot: "{ce}The player {0} was NOT teleported back because no safe spot was found." - notTeleportedNoSafeSpotCmd: "{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardess this point." - - tp: - NaN: "{ce}The coordinates must be three valid numbers." - targetOffline: "{ce}{0} is offline!" - teamDoesNotExists: "{ce}This team is not registered." - - spectators: - syntaxError: "{ce}Syntax error, see /uh spec." - unknownCommand: "{ce}Unknown command. See /uh spec for available commands." - offline: "{ce}The player {0} is not online." - - add: - success: "{cs}The player {0} is now a spectator." - - remove: - success: "{cs}The player {0} is now a player." - - list: - nothing: "{ce}There isn't any spectator to list." - countSpectators: "{ci}{0} registered spectator(s)." - countOnlyInitial: "{ci}This count includes only the initial spectators." - itemSpec: "{lightpurple} - {0}" - - freeze: - frozen: "{cst}You where frozen by {0}." - unfrozen: "{cst}You where unfrozen by {0}." - - playerFrozen: "{cs}{0} is now frozen." - playerUnfrozen: "{cs}{0} is now unfrozen." - - playerOnly: "{ce}You need to be a player to execute this command this way." - offline: "{ce}{0} is offline!" - - scoreboard: "{darkaqua}Game frozen" - - broadcast: - globalFreeze: "{darkaqua}The entire game is now frozen." - globalUnfreeze: "{darkaqua}The game is now unfrozen." - - borders: - syntaxError: "{ce}Syntax error, see /uh border." - NaN: "{ce}“{0}” is not a number..." - - current: - messageSquared: "{ci}The current map size is {0}*{0}." - messageCircular: "{ci}The current diameter of the map is {0} blocks." - - set: - playersOutsideCanceled: "{ce}Some players are outside the future border, so this operation was cancelled." - playersOutsideCanceledCmd: "{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to this point." - playersOutsideCanceledWarnWorldBorder: "{ce}WARNING: {ci}because WorldBorder is not installed, players out of the border will not be teleported!" - - broadcastSquared: "{lightpurple}The size of the map is now {0}*{0}." - broadcastCircular: "{lightpurple}The diameter of the map is now {0} blocks." - - warning: - canceled: "{cs}Warning canceled." - - set: "{cs}Future size saved. All players outside this future border will be warned every {0} seconds." - - messageSquared: "{ce}You are currently out of the future border of {0}*{0} blocks." - messageCircular: "{ce}You are currently out of the future border (diameter of {0} blocks)." - - messageDistance: "{ci}You have {0} blocks to go before being inside." - messageDistanceTime: "{ci}You have {0} blocks to go before being inside, and {1} minutes to do so." - - nameTimer: "Border shrinking" - - timerUp: "{cs}The timer before the new border is up!" - - check: - allPlayersInside: "{cs}All players are inside the given border." - countPlayersOutside: "{ci}There are {0} players outside the given border." - - itemPlayerFar: "{lightpurple} - {red}{0}{ci} (far away from the border)" - itemPlayerClose: "{lightpurple} - {yellow}{0}{ci} (close to the border)" - itemPlayerVeryClose: "{lightpurple} - {green}{0}{ci} (very close to the border)" - - timers: - syntaxError: "{ce}Syntax error, see /uh timers." - durationSyntaxError: "{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or hh:mm:ss." - timerDoesNotExists: "{ce}This timer is not registered." - alreadyExists: "{ce}A timer called {0}{ce} already exists; please choose another name." - - added: "{cs}The timer {0}{cs} (duration {1}) has been registered." - set: "{cs}The duration of the timer {0}{cs} is now {1}." - displayed: "{cs}The timer {0}{cs} is now displayed." - hidden: "{cs}The timer {0}{cs} is now hidden." - started: "{cs}The timer {0}{cs} was started." - paused: "{cs}The timer {0}{cs} is now paused." - resumed: "{cs}The timer {0}{cs} was resumed." - stopped: "{cs}The timer {0}{cs} was stopped." - removed: "{cs}The timer {0}{cs} has been deleted." - - list: - count: "{ci}{0} timer(s) are registered." - itemRunning: "{green} • {ci}{0}{ci} - total {1} seconds - {2}" - itemPaused: "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" - itemStopped: "{red} • {ci}{0}{ci} - total {1} seconds" - - protips: - base: "{darkpurple}ProTip!" - - teamchat: - lock: "{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." - useTCommand: "{gray}You can send a team-chat message with {cc}/t <message>{gray}." - useGCommand: "{gray}You can send a global message using {cc}/g <message>{gray}." - - crafts: - goldenHead: "{gray}You can craft golden apples with heads (same recipe with a head instead of an apple)." - compassEasy: "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder." - compassMedium: "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder; in the center, an ender pearl." - compassHard: "{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a spider eye and a gunpowder; in the center, an Eye of Ender." - glisteringMelon: "{gray}The glistering melon is crafted with a melon and a gold block." - noEnchGoldenApple: "{gray}The enchanted golden apple is disabled for this game." - - start: - invincibility: "{gray}Fallen on a tree? Jump, you have 25 seconds left to remain invincible." - diff --git a/src/main/resources/i18n/fr_FR.po b/src/main/resources/i18n/fr_FR.po new file mode 100644 index 0000000..cd773ab --- /dev/null +++ b/src/main/resources/i18n/fr_FR.po @@ -0,0 +1,2505 @@ +# Copyright or © or Copr. Amaury Carrade (2014 - 2016) +# +# http://amaury.carrade.eu +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-12-19 16:34+0100\n" +"PO-Revision-Date: 2016-12-19 16:35+0100\n" +"Last-Translator: Amaury Carrade\n" +"Language-Team: Amaury Carrade\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"X-Generator: Poedit 1.7.5\n" + +#. The name of the warning timer displaying the time left before the next border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:86 +msgid "Border shrinking" +msgstr "Réduction" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:365 +msgid "{cs}All players are inside the given border." +msgstr "{cs}Tous les joueurs sont à l'intérieur de cette bordure." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:369 +msgid "{ci}There are {0} players outside the given border." +msgstr "{ci}Il y a {0} joueurs hors de cette bordure." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:375 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "{lightpurple} - {red}{0}{ci} (loin de la bordure)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:379 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "{lightpurple} - {yellow}{0}{ci} (proche de la bordure)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:383 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "{lightpurple} - {green}{0}{ci} (très proche de la bordure)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:429 +msgid "{red}Warning!" +msgstr "{red}Attention !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:429 +msgid "{white}The border begins to shrink..." +msgstr "{white}La bordure commence à se réduire..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:431 +msgid "{red}{bold}The border begins to shrink..." +msgstr "{red}{bold}La bordure commence à se réduire..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:432 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" +"{gray}Elle réduira d'un bloc toutes les {0} seconde(s) jusqu'à atteindre {1} " +"blocs de diamètre." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "" +"{gray}Verrouillez le chat d'équipe avec {cc}/togglechat{gray}, qui permet de " +"passer d'un chat à l'autre." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "" +"{gray}Vous pouvez envoyer un message à tout le monde avec {cc}/g " +"<message>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "" +"{gray}Vous pouvez envoyer un message à votre équipe avec {cc}/t " +"<message>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "" +"{gray}Vous pouvez fabriquer des pommes d'or avec les têtes (même recette " +"avec une tête à la place de la pomme)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder." +msgstr "" +"{gray}La boussole se fabrique avec dans les coins un os, une chaire de " +"zombie, un œil d'araignée et une poudre à canon." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder; in the center, an ender pearl." +msgstr "" +"{gray}La boussole se fabrique avec dans les coins un os, une chaire de " +"zombie, un œil d'araignée et une poudre à canon ; au centre une Perle du " +"Néant." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a " +"spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "" +"{gray}La boussole se fabrique avec dans les coins un os, une chaire de " +"zombie, un œil d'araignée et une poudre à canon ; au centre un Œil du Néant." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "" +"{gray}La pastèque scintillante se fabrique avec une pastèque et un bloc d'or." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "{gray}La pomme d'or enchantée est désactivée pour cette partie." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "" +"{gray}Tombé(e) sur un arbre ? Sautez, il vous reste quelques dizaines de " +"secondes d'invincibilité." + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:132 +msgid "{darkpurple}ProTip!" +msgstr "{darkpurple}Astuce !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:209 +msgid "Ultra Hardcore plugin loaded." +msgstr "Plugin Ultra Hardcore chargé." + +#. Title of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:70 +msgid "{red}Team deleted" +msgstr "{red}Équipe supprimée." + +#. Lore of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:72 +msgid "{gray}The team {0}{gray} was deleted by another player." +msgstr "{gray}L'équipe {0}{gray} a été supprimée par un autre joueur." + +#. Lore of the item displayed if a team was deleted while someone edited it in a GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamActionGUI.java:75 +msgid "{gray}Press {white}Escape{gray} to go back to the teams list." +msgstr "" +"{gray}Appuyez sur {white}Échap{gray} pour retourner à la liste des équipes." + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:58 +msgid "{0} » {darkred}Delete" +msgstr "{0} » {darkred}Supprimer" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:72 +msgid "{green}Keep this team alive" +msgstr "{green}Garder cette équipe en vie" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:84 +msgid "{red}Delete this team {italic}forever" +msgstr "{red}Supprimer cette équipe {italic}pour l'éternité" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:67 +msgid "{0} » {black}Members" +msgstr "{0} » {black}Membres" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:131 +msgid "{green}« Go back" +msgstr "{green}« Retour" + +#. The title of a button to select a player (a skull button). {0} = player's display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "{reset}{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "{gray}En ligne" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "{gray}Hors ligne" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "{gray}Équipe : {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "{gray}Équipe : aucune" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:98 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "{darkgray}» {white}Cliquez {gray}pour retirer ce joueur" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:98 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "{darkgray}» {white}Cliquez {gray}pour ajouter ce joueur" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "{0} » {black}Couleur" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:66 +msgid "Teams » {black}{0}" +msgstr "Équipes » {black}{0}" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:79 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "{white}{0} {gray}membre" +msgstr[1] "{white}{0} {gray}membres" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{white}Click with a banner {gray}to update this team's banner" +msgstr "" +"{white}Cliquez avec une bannière {gray}pour changer la bannière de l'équipe" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:89 +msgid "{green}Update the color" +msgstr "{green}Changer la couleur" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:91 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "{gray}Actuelle : {white}{0}" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:98 +msgid "{green}Rename the team" +msgstr "{green}Renommer l'équipe" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:100 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "{gray}Actuel : {white}{0}" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:107 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "{green} • " + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "{red} • " + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{green}Add or remove players" +msgstr "{green}Modifier les membres" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:122 +msgid "{red}Delete this team" +msgstr "{red}Supprimer cette équipe" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:124 +msgid "{gray}Cannot be undone" +msgstr "{gray}Non annulable" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:75 +msgid "{black}Select a team {reset}({0})" +msgstr "{black}Sélectionnez votre équipe {reset}({0})" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:87 +msgid "{white}Rename your team" +msgstr "{white}Renommer votre équipe" + +#. Warning displayed in the "Rename your team" button, if the player is not in a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{gray}You have to be in a team" +msgstr "{gray}Vous devez être dans une équipe" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:98 +msgid "{white}New team" +msgstr "{white}Nouvelle équipe" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:116 +msgid "{blue}Players" +msgstr "{blue}Joueurs" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:120 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "{darkgray}- {white}{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "{darkgray}» {white}Cliquez {gray}pour rejoindre l'équipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {red}This team is full" +msgstr "{darkgray}» {red}Cette équipe est pleine" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "{darkgray}» {white}Cliquez {gray}pour quitter l'équipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:144 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "{darkgray}» {white}Cliquez droit {gray}pour gérer cette équipe" + +#. Title of the team item in the teams selector GUI (with max). {0}: team display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:182 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "{white}Équipe {0} {gray}({1}/{2})" + +#. Title of the team item in the teams selector GUI (without max) {0}: team display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:184 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "{white}Équipe {0} {gray}({1} joueur)" +msgstr[1] "{white}Équipe {0} {gray}({1} joueurs)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:198 +msgid "{red}No team created" +msgstr "{cs}Aucune équipe créée" + +#. Subtitle of the item displayed in the teams selector GUI if there isn't anything to display. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:201 +msgid "{gray}Click the emerald button below to create one." +msgstr "{gray}Cliquez sur le bouton d'émeraude ci-dessous pour en créer une." + +#. Subtitle of the item displayed in the teams selector GUI if there isn't anything to display and the player cannot create a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:203 +msgid "{gray}Wait for an administrator to create one." +msgstr "{gray}Patientez le temps qu'un administrateur en ajoute une." + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "{gray}1. {white}{bold}Couleur de l'équipe" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "{gray}2. {white}{bold}Nom de l'équipe" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "{gray}3. {white}{bold}Membres de l'équipe" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "Nouvelle équipe » {black}Nom" + +#. The title of the button opening the sign to write the team name (creator GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "{white}Nommer l'équipe" + +#. The legend of the button opening the sign to write the team name (creator GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" +"{gray}Cliquez ici pour ouvrir un panneau, et écrivez le nom de l'équipe " +"dedans." + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "Nouvelle équipe » {black}Couleur" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "{lightpurple}Couleur aléatoire" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "Nouvelle équipe » {black}Membres" + +#. The summary title in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "{blue}{bold}Récapitulatif" + +#. The team name in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "{gray}Nom : {white}{0}" + +#. The team color in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "{gray}Couleur : {0}" + +#. The team members count in the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "{gray}Membres : {white}{0}" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "{green}Créer l'équipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "{lightpurple}Ajouté !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "{darkgray}» {white}Cliquez {gray}pour l'ajouter à l'équipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:170 +msgid "{cs}Team created." +msgstr "{cs}Équipe créée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:176 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:117 +msgid "{ce}This team already exists." +msgstr "{ce}Cette équipe existe déjà." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:148 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "{cs}Votre équipe s'appelle désormais {0}{cs}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:321 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "{aqua}Vous faites désormais partie de l'équipe {0}{aqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:374 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "{darkaqua}Vous ne faites plus partie de l'équipe {0}{darkaqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:212 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "" +"{ce}Vous n'avez pas le droit d'envoyer des messages privés à votre équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:90 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:217 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "" +"{ce}Vous n'avez pas le droit d'entrer dans le chat privé d'une autre équipe." + +#. Format of a private team message from a team member. {0} = sender display name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:100 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "{gold}[{0}{gold} -> son équipe] {reset}{1}" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:106 +msgid "{ce}You are not in a team!" +msgstr "{ce}Vous n'êtes pas dans une équipe !" + +#. Format of a private team message from a non-team-member. {0} = sender display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:113 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "{gold}[{0}{gold} -> équipe {1}{gold}] {reset}{2}" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:514 +msgid "{gold}Click on the names below to join a team" +msgstr "{gold}Cliquez ci-dessous pour rejoindre une équipe" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:535 +msgid "{0} ({red}dead{reset})" +msgstr "{0} ({red}mort{reset})" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:540 +msgid "{0} ({green}alive{reset})" +msgstr "{0} ({green}en vie{reset})" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:550 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "{gray}[{white}{0}{gray}/{white}{1}{gray}]" + +#. Team count without max players (ex. [3]) followed in-game by the team name. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:552 +msgid "{gray}[{white}{0}{gray}]" +msgstr "{gray}[{white}{0}{gray}]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:554 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "{0} joueur dans cette équipe" +msgstr[1] "{0} joueurs dans cette équipe" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:565 +#, java-format +msgid "You are in the team {0}" +msgstr "Vous êtes dans l'équipe {0}" + +#. Tooltip on the chat team selector GUI when the player is not in the team. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:567 +#, java-format +msgid "Click here to join the team {0}" +msgstr "Cliquez ici pour rejoindre l'équipe {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:577 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "{darkred}[×] {red}Cliquez ici pour quitter votre équipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "{gray}Exécutez /join pour réafficher ceci" + +#. No teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "{ce}Il n'y a aucune équipe disponible." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:621 +msgid "{gold}Your team: {0}" +msgstr "{gold}Votre équipe : {0}" + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:158 +msgid "jayjay" +msgstr "jayjay" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:236 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "{0}L'équipe {1} est vaincue !" + +#. A message displayed to the players under the death screen, about the respawn possibility even if the death screen says the opposite (in hardcore mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:280 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} VOUS POUVEZ " +"REVENIR{lightpurple}, cliquez sur {italic}Ressusciter {lightpurple}sur " +"l'écran suivant." + +#. The kick message displayed if a player tries to relog after his death and it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:385 +msgid "You are dead!" +msgstr "Vous êtes mort !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:458 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "" +"{darkred}[UHC] {ce}WorldBorder pas installé : bordures non surveillées !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:459 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game " +"(warnings excluded)." +msgstr "" +"{gray}Aussi, sans WorldBorder, impossible de réduire la bordure pendant le " +"jeu (sauf avertissements)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:460 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "{gray}Installez le plugin ; UHPlugin va automatiquement le configurer." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:470 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "{darkred}[UHC] {ce}ProtocolLib est requis mais non installé !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:471 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "{gray}Les options suivantes requièrent la présence de ProtocolLib :" + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:475 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "{darkgray} - {gray}{0}" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:488 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "{gray}ProtocolLib est disponible ici : {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:607 +msgid "{cs}The timer before the new border is up!" +msgstr "{cs}Le temps imparti avant la nouvelle bordure est écoulé !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:639 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "{aqua}-------- Fin de l'épisode {0} [forcé par {1}] --------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:643 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "{aqua}-------- Fin de l'épisode {0} --------" + +#. The title displayed when the episode change. {0} = new episode number; {1} = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:655 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "{darkaqua}Épisode {aqua}{0}" + +#. Broadcast +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:679 +msgid "{green}--- GO ---" +msgstr "{green}--- GO ---" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:687 +msgid "{darkgreen}Let's go!" +msgstr "{darkgreen}C'est parti !" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:689 +msgid "{green}Good luck, and have fun" +msgstr "{green}Bonne chance et bon jeu à tous" + +#. All players are notified +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:821 +msgid "{gold}{0} returned from the dead!" +msgstr "{gold}{0} est revenu d'entre les morts !" + +#. The title of the item given before the game to select a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java:110 +msgid "{green}{bold}Select a team {gray}(Right-Click)" +msgstr "{green}{bold}Choisir une équipe {gray}(Clic droit)" + +#. The lore of the item given before the game to select a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/BeforeGameListener.java:112 +msgid "{gray}Right-click to select your team for this game" +msgstr "{gray}Cliquez-droit pour sélectionner votre équipe pour ce jeu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:285 +msgid "{aqua}Golden head" +msgstr "{aqua}Tête d'or" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:202 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:286 +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Tête d'or" + +#. Error message if a player tries to use his pointing compass without rotten flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:305 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "{gray}{italic}Vous n'avez pas de chair de zombie." + +#. Error message if a player tries to use his pointing compass without a player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:336 +msgid "{gray}{italic}Only silence answers your request." +msgstr "{gray}{italic}Seul le silence comble votre requête." + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:343 +msgid "{gray}The compass now points to the closest player." +msgstr "{gray}Le compas pointe désormais vers le joueur le plus proche." + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:153 +#, java-format +msgid "Death point of {0}" +msgstr "Ici disparu {0}" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:232 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "Lieu de démarrage de l'équipe {0}" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:237 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:294 +#, java-format +msgid "Spawn point of {0}" +msgstr "Lieu de démarrage de {0}" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:280 +msgid "Made from the fallen head of a malignant monster" +msgstr "Fabriquée depuis la tête tranchée d'un monstre maléfique" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "Fabriquée depuis la tête tranchée de {0}" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:388 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Tête d'or" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:394 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Tête d'or" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:421 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Tête d'or" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:427 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Tête d'or" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:140 +msgid "{gray}Episode {white}{0}" +msgstr "{gray}Épisode {white}{0}" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:158 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "{white}{0}{gray} joueur" +msgstr[1] "{white}{0}{gray} joueurs" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:162 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "{white}{0}{gray} équipe" +msgstr[1] "{white}{0}{gray} équipes" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:207 +msgid "{bold}Your team" +msgstr "{bold}Votre équipe" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:280 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "{white}{0}{gray} joueur tué" +msgstr[1] "{white}{0}{gray} joueurs tués" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:311 +msgid "{blue}{bold}Border" +msgstr "{blue}{bold}Bordure" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:319 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "{white}{0} bloc de large" +msgstr[1] "{white}{0} blocs de large" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:322 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "{gray}Diamètre : {white}{0} bloc" +msgstr[1] "{gray}Diamètre : {white}{0} blocs" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:338 +msgid "{white}{0} {1}" +msgstr "{white}{0} {1}" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}X: {white}{0} {1}" +msgstr "{gray}X: {white}{0} {1}" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:345 +msgid "{gray}Z: {white}{0} {1}" +msgstr "{gray}Z: {white}{0} {1}" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:386 +msgid "{darkaqua}Game frozen" +msgstr "{darkaqua}En pause" + +#. Default nick name when a player cannot be recognized. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/SidebarPlayerCache.java:133 +msgid "Unknown" +msgstr "Inconnu" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:120 +msgid "{red}{bold}Rules and informations" +msgstr "{red}{bold}Règles et informations" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:131 +msgid "{darkgray}- {reset}{0}" +msgstr "{darkgray}- {reset}{0}" + +#. Episode in the player list ({episodeText} replacement). {0} = current episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:115 +#, java-format +msgid "Episode {0}" +msgstr "Épisode {0}" + +#. Players in the player list ({playersText} replacement). {0} = current alive players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "{0} joueur" +msgstr[1] "{0} joueurs" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} team" +msgid_plural "{0} teams" +msgstr[0] "{0} équipe" +msgstr[1] "{0} équipes" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:90 +msgid "Waiting for players..." +msgstr "En attente de joueurs..." + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:99 +msgid "Starting in progress..." +msgstr "Démarrage en cours..." + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:114 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "Partie en cours ! {0} joueur encore en vie." +msgstr[1] "Partie en cours ! {0} joueurs encore en vie." + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive count. Plural based on players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:119 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "Partie en cours ! {0} joueur en vie dans {1} équipe." +msgstr[1] "Partie en cours ! {0} joueurs en vie dans {1} équipes." + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:136 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "Partie terminée ; félicitation à {0} pour sa victoire !" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:141 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "Partie terminée ; l'équipe {0} remporte la victoire !" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "{0}{gray}:{white}{1}{gray}:{white}{2}" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "{white}{0}{gray}:{white}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "{aqua}------ Commandes liées au jeu ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "{aqua}------ Commandes liées aux bugs ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "{aqua}------ Commandes diverses ------" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:108 +msgid "{ce}Usage: /{0} <message>" +msgstr "{ce}Utilisation : /{0} <message>" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "{aqua}------ Commandes de gestion des points de démarrage ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "" +"{cc}/uh spawns {ci}: gère les points de démarrage. Exécutez /uh spawns pour " +"plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "{ce}Les coordonnées doivent être trois nombres." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "{ce}Cette équipe n'est pas enregistrée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "{ce}{0} est hors-ligne !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "{aqua}------ Commandes de téléportation ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: téléporte une équipe " +"au lieu ou au joueur indiqué." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: téléporte les spectateurs " +"(i.e. les joueurs non-vivants) au lieu ou au joueur indiqué." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "" +"{cc}/uh tp {ci}: téléporte les spectateurs ou une équipe. Consultez /uh tp " +"pour plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "{yellow}{0} - version {1}" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "et" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "Plugin réalisé avec amour par {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "Numéro de construction : {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "Numéro de construction indisponible." + +#. Translation +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "{aqua}------ Traductions ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "Langue courante : {0} (traduit par {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "Langue par défaut : {0} (traduit par {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "{aqua}------ Licence ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "Publié sous la licence CeCILL-B." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "" +"{cc}/uh about {ci}: informations à propos du plugin et des traductions." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:73 +msgid "{cs}Warning canceled." +msgstr "{cs}Avertissement annulé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:88 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "" +"{cs}Future taille enregistrée. Les joueurs hors de la bordure vont être " +"avertis toutes les {0} seconde." +msgstr[1] "" +"{cs}Future taille enregistrée. Les joueurs hors de la bordure vont être " +"avertis toutes les {0} secondes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "{ce}“{0}” n'est pas un nombre..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:118 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" +"{cc}/uh border warning <futurDiamètre> [minutesAvantRéduction] {ci}: avertit " +"tous les joueurs hors de la future bordure donnée. Ce n'est qu'un " +"avertissement, rien de plus." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:118 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "{cc}/uh border warning cancel {ci}: annule un précédent avertissement." + +#. Some players are outside +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "" +"{ce}Certains joueurs étant hors de cette nouvelle bordure, l'opération a été " +"annulée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "" +"{ci}Utilisez {cc}/uh border set {0} force{ci} pour changer la taille de la " +"carte malgré tout." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "" +"{ce}ATTENTION: {ci}WorldBorder n'étant pas installé, les joueurs hors de la " +"bordure ne seront pas téléportés !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:113 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "{lightpurple}La carte a désormais un diamètre de {0} bloc." +msgstr[1] "{lightpurple}La carte a désormais un diamètre de {0} blocs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:117 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "{lightpurple}La taille de la carte est désormais de {0}×{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:147 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" +"{cc}/uh border set <diamètre> [force] {ci}: change la taille de la carte. Si " +"le paramètre “force” n'est pas donné, l'opération sera annulée s'il existe " +"des joueurs hors de la bordure." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "" +"{cc}/uh border check <diamètre> {ci}: retourne la liste des joueurs hors de " +"la bordure." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "{ci}La carte a actuellement un diamètre de {0} bloc." +msgstr[1] "{ci}La carte a actuellement un diamètre de {0} blocs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "{ci}La taille actuelle de la carte est {0}×{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "{cc}/uh border get {ci}: retourne la taille actuelle de la carte." + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "{ci}{0} joueur en vie, dans {1} équipe." +msgstr[1] "{ci}{0} joueurs en vie, répartis dans {1} équipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "{ci}Le jeu n'est pas encore démarré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "Actuellement connecté(e)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "Actuellement hors-ligne" + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "Équipe : {0}" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "{gray} - " + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "{green}vivant" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "{0} demi-cœurs" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "{red}mort" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "{cc}/uh infos {ci}: affiche des informations à propos du jeu en cours." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "" +"{ce}Les valeurs de faim et de saturation doivent être des nombres " +"(possiblement à virgule pour la saturation) !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "" +"{cc}/uh feedall [faim=20] [saturation=max] {ci}: nourrit tous les joueurs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "{cs}Point de démarrage ajouté dans le monde {0} : {1};{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "" +"{ce}Vous ne pouvez pas ajouter un point de démarrage hors des bordures." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "" +"{ce}Impossible d'ajouter ce point de démarrage : aucun endroit sûr trouvé " +"dans le Nether." + +#. /uh spawns add <x>: Two coordinates needed! +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "{ce}Vous devez spécifier deux coordonnées." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "{ce}Ceci n'est pas un nombre !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "" +"{cc}/uh spawns add [<x> <z>]{ci}: ajoute un point de démarrage à la position " +"de l'exécutant ou aux coordonnées données." + +#. Solo mode? +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "{ci}Aucune équipe trouvée : le jeu est considéré comme solo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "" +"{ci}Certains joueurs ne sont pas dans une équipe ; leur nombre a été ajoutés " +"aux points de démarrage à générer." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "{ce}Le monde {0} n'existe pas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "{ci}Vous avez demandé de ne rien générer. Rien ne sera généré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "{ce}La méthode de génération « {0} » n'est actuellement pas supportée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "" +"{ce}Vous avez demandé l'impossible : il y a trop de points sur une trop " +"petite surface. Diminuez le nombre de points à générer ou la distance " +"minimale entre deux points." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "{cs}Génération des points de démarrage effectuée avec succès." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "{aqua}Commande" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" +"{cc}/uh spawns generate <circular|grid|random> [taille] [distanceMin] " +"[nombre] [xCentre] [zCentre] [monde]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "{aqua}Formes" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr "" +" - {cc}random{ci} : génère des points aléatoirement sur la carte, avec une " +"distance minimale entre eux." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr "" +" - {cc}grid{ci} : génère les points sur des carrés concentriques, en " +"commençant par le plus grand. La distance entre deux points est constante." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" +" - {cc}circular{ci}: génère les points sur des cercles concentriques, avec " +"une distance minimale entre deux points. Sur chaque cercle, l'angle (et donc " +"la distance) entre deux points est constant." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "{aqua}Arguments" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr "" +" - {cc}taille{ci} : la taille de la région dans laquelle les points vont " +"être générés. La région est carrée ou circulaire, selon la configuration. " +"Par défaut : la taille de la carte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr "" +" - {cc}distanceMin{ci} : la distance minimale entre deux points. Par " +"défaut : 250 blocs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr "" +" - {cc}nombre{ci} : le nombre de points à générer. Par défaut : le nombre de " +"joueurs ou d'équipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr "" +" - {cc}xCentre{ci}, {cc}zCentre{ci} : le centre de la région dans laquelle " +"les points sont générés. Par défaut : le point d'apparition du monde." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr " - {cc}monde{ci} : le monde dans lequel les points seront générés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "" +"{cc}/uh spawns generate {ci}: génère automatiquement des points de " +"démarrage. Consultez /uh spawns generate pour plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "" +"{cc}/uh spawns dump {ci}: affiche les points de démarrage dans un format " +"exportable. {gray}Utilisez ceci pour afficher les points sur un graph, par " +"exemple." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "{ce}Il n'y a pas de point de démarrage enregistré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "{ci}Il y a {0} points de démarrage enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "{lightpurple}Monde {0}" + +#. A spawn point in the /uh spawns list command (in the overworld) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:130 +msgid "{green}{0}{darkgreen};{green}{1}" +msgstr "{green}{0}{darkgreen};{green}{1}" + +#. A spawn point in the /uh spawns list command (in the Nether) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:134 +msgid "{red}{0}{darkred};{red}{1}" +msgstr "{red}{0}{darkred};{red}{1}" + +#. A spawn point in the /uh spawns list command (in the End) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:138 +msgid "{yellow}{0}{gold};{yellow}{1}" +msgstr "{yellow}{0}{gold};{yellow}{1}" + +#. A spawn point in the /uh spawns list command (in a custom world) +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:142 +msgid "{gray}{0}{darkgray};{gray}{1}" +msgstr "{gray}{0}{darkgray};{gray}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:185 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "{cc}/uh spawns list {ci}: liste les points de démarrage enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "{cs}Tous les points de démarrage ont été supprimés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "" +"{cc}/uh spawns reset {ci}: supprime tous les points de démarrage enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "{cs}Le point de démarrage {1};{2} du monde {0} a été supprimé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" +"{cc}/uh spawns remove [<x> <z>] {ci}: supprime les points de démarrage aux " +"coordonnées spécifiées, ou à la position de l'envoyeur sans coordonnées." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +msgid "{ce}The player {0} is not online." +msgstr "{ce}Le joueur {0} n'est pas connecté." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "{ce}Pas de localisation de mort enregistrée pour le joueur {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "{cs}Le joueur {0} a été téléporté là où il est mort." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "" +"{ce}Le joueur {0} n'a PAS été téléporté car aucun point de téléportation sûr " +"n'a été trouvé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" +"{ci}Utilisez {cc}/uh tpback {0} force{ci} pour le téléporter malgré tout." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "" +"{cc}/uh tpback <joueur> [force] {ci}: téléporte un joueur au lieu de sa mort " +"en toute sécurité." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "{ce}Le jeu n'est pas encore démarré !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "{ce}Il n'y a pas qu'une équipe encore en vie !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "" +"{cc}/uh finish {ci}: affiche le nom du/des vainqueurs et lance des feux " +"d'artifices." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" +"{ce}Les points de démarrage n'ont pas encore été assignés aux joueurs, car " +"le jeu n'a pas encore démarré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "{ce}Pas de localisation de démarrage enregistrée pour le joueur {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "{cs}Le joueur {0} a été téléporté à son point de démarrage attribué." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" +"{ce}Le joueur {0} n'a PAS été téléporté car aucun point de téléportation sûr " +"n'a été trouvé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" +"{ci}Utilisez {cc}/uh tpspawn {0} force{ci} pour le téléporter malgré tout." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his " +"spawn location." +msgstr "" +"{cc}/uh tpspawn <joueur> [force] {ci}: téléporte un joueur à son point de " +"démarrage attribué en toute sécurité." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "{ce}Ce joueur ne joue pas ou n'est pas mort !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "" +"{cs}Comme {0} est déconnecté, il sera ressuscité dés qu'il se connectera. " +"S'il l'était, il n'est plus banni." + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "{ce}{0} n'est pas mort !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "{cc}/uh resurrect <joueur> {ci}: fait revivre un joueur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:117 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "{ce}Cette équipe n'existe pas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:100 +msgid "{ce}Unable to retrieve the player {0}." +msgstr "{ce]Impossible de trouver le joueur {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:134 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:103 +msgid "" +"{ce}In offline mode, you cannot add players if they never came to this " +"server." +msgstr "" +"{ce}En mode hors-ligne, vous ne pouvez pas ajouter de joueurs qui ne se sont " +"jamais connectés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:143 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "{cs}Le joueur {0} a été ajouté à l'équipe {1}{cs} avec succès." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:190 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" +"{cc}/uh team join <joueur> <nomÉquipe ...> {ci}: ajoute un joueur dans " +"l'équipe donnée. Le nom de l'équipe est sa couleur, ou le nom explicite " +"donné." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "{cs}Toutes les équipes ont été supprimées." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "{cc}/uh team reset {ci}: supprime toutes les équipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "" +"{ce}Impossible d'ajouter l'équipe ; vérifiez le nom de la couleur. Conseil : " +"utilisez l'autocomplétion." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:121 +msgid "{cs}Team {0}{cs} added." +msgstr "{cs}Équipe {0}{cs} ajoutée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:163 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "" +"{cc}/uh team add <couleur> [<nom ...>]{ci}: ajoute une équipe de la couleur " +"donnée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:92 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "" +"{ce}Le joueur {0} est déconnecté et ne s'est jamais connecté au serveur " +"auparavant !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:109 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "{cs}Le joueur {0} a été retiré de son équipe avec succès." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:143 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "{cc}/uh team leave <joueur> {ci}: retire un joueur de son équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "{cs}Équipe {0} supprimée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "{cc}/uh team remove <nom ...> {ci}: supprime une équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "{ce}Il n'y a pas d'équipe à lister." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "{0} ({1} joueur)" +msgstr[1] "{0} ({1} joueurs)" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "{cc}/uh team list {ci}: liste toutes les équipes et leurs membres." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:74 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:77 +msgid "{ce}Either this team does not exists, or you are not in a team." +msgstr "{ce}Cette équipe n'existe pas, ou vous n'êtes pas dans une équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:78 +msgid "{ce}You must run this command with a banner in your main hand." +msgstr "" +"{ce}Vous devez avoir une bannière dans votre main principale pour lancer " +"cette commande." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:83 +msgid "{cs}The banner of the team {0}{cs} was successfully updated." +msgstr "{cs}La bannière de l'équipe {0}{cs} a été mise à jour avec succès." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerCommand.java:109 +msgid "" +"{cc}/uh team banner [team name ...] {ci}: updates the team's banner using " +"the banner in the sender hand. If the team name is not provided, uses the " +"sender's team." +msgstr "" +"{cc}/uh team banner [nom de l'équipe ...] {ci}: change la bannière de " +"l'équipe en utilisant la bannière dans la main de l'exécuteur. Si le nom de " +"l'équipe n'est pas spécifié, celle de l'exécuteur est utilisée." + +#. Error message of /uh team bannerreset from the console without name +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:71 +msgid "{ce}From the console, you must provide a team name." +msgstr "{ce}Depuis la console, vous devez préciser le nom d'une équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:82 +msgid "" +"{cs}The banner of the team {0}{cs} was successfully reset to the default one." +msgstr "{cs}La bannière de l'équipe {0}{cs} a été réinitialisée avec succès." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamBannerResetCommand.java:108 +msgid "" +"{cc}/uh team bannerreset [team name ...] {ci}: resets the banner of the team " +"to the default. If the team name is not provided, uses the sender's team." +msgstr "" +"{cc}/uh team bannerreset [nom de l'équipe ...] {ci}: réinitialise la " +"bannière de l'équipe à celle générée par défaut. Si le nom de l'équipe n'est " +"pas spécifié, celle de l'exécuteur est utilisée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" +"{cc}/uh team gui {ci}: ouvre une interface graphique pour gérer et rejoindre " +"les équipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" +"{ce}Impossible d'inverser le mode d'espoinnage de {0} car il (ou elle) n'est " +"pas connecté(e)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "{cs}Espoinnage {darkred}désactivé{cs} pour {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "{cs}Espionnage {darkgreen}activé{cs} pour {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" +"{cc}/uh team spy [joueur] {ci}: permet de recevoir (soit-même ou le joueur " +"ciblé) tous les chats d'équipe (en lecture seule). Exécutez une autre fois " +"pour interrompre." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "{aqua}------ Commandes liées aux comptes à rebours ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "" +"{cc}/uh timers {ci}: gère les comptes à rebours. Consultez /uh timers pour " +"plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:110 +msgid "{aqua}------ Team commands ------" +msgstr "{aqua}------ Commandes liées aux équipes ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:111 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the " +"given team. Without arguments, displays the chat-based team selector." +msgstr "" +"{cc}/join [joueur] <équipe ...> {ci}: ajoute “joueur” (ou l'envoyeur) dans " +"l'équipe donnée. Sans argument, affiche le sélecteur d'équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:112 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "" +"{cc}/leave [joueur] {ci}: retire “joueur” (ou l'envoyeur) de son équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:119 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "" +"{cc}/uh team {ci}: gère les équipes. Exécutez /uh team pour plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "{aqua}------ Commandes liées aux bordures ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "" +"{cc}/uh border {ci}: gère la bordure. Exécutez /uh border pour plus de " +"détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "" +"{ce}Hey, ce n'est pas un nombre de demi-coeurs... C'est un texte... Pfff." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "{ce}S'pèce de tueur en série !" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "{ce}La vie de {0} n'a pas été changée, pour ne pas le/la tuer." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "" +"{cc}/uh healall [demi-coeurs=20|±diff] {ci}: change la vie de tous les " +"joueurs, et non d'un seul." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "la console" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "" +"{ce}Vous ne pouvez pas passer l'épisode actuel car le jeu n'a pas démarré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "{cc}/uh shift {ci}: passe un épisode." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "{cst}Génération des murs en cours..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "{ci}Depuis la console, génération du mur du monde par défaut, {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the " +"config are probably invalid." +msgstr "" +"{ce}Impossible de générer le mur: voir logs pour plus de détails. Les blocs " +"configurés sont probablement invalide." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "" +"{ce}Une erreur s'est produite, consultez la console pour plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "{cst}Génération terminée." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "{cc}/uh generatewalls {ci}: génère les murs suivant la configuration." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "{ce}Ce compteur n'est pas enregistré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "{cs}Le compteur {0}{cs} a été arrêté." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "" +"{cc}/uh timers stop <title ...> {ci}: force l'arrêt d'un compteur. Il est " +"retiré du scoraboard." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "{cs}Le compteur {0}{cs} a démarré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "{cc}/uh timers start <titre ...> {ci}: démarre un compte à rebours." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "{cs}Le compteur {0}{cs} est désormais masqué." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "" +"{cc}/uh timers hide <titre ...> {ci}: retire un compteur du scoreboard. " +"N'arrête pas le compteur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "{ci}Il y a {0} compteur enregistré." +msgstr[1] "{ci}Il y a {0} compteurs enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{yellow} • {ci}{0}{ci} - {1} seconde au total - {2}" +msgstr[1] "{yellow} • {ci}{0}{ci} - {1} secondes au total - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:82 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{green} • {ci}{0}{ci} - {1} seconde au total - {2}" +msgstr[1] "{green} • {ci}{0}{ci} - {1} secondes au total - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:92 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "{red} • {ci}{0}{ci} - {1} seconde au total" +msgstr[1] "{red} • {ci}{0}{ci} - {1} secondes au total" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:123 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "{cc}/uh timers list {ci}: liste les compteurs enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "{cs}Le compteur {0}{cs} est désormais affiché." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard. " +"Automatic when a timer is started." +msgstr "" +"{cc}/uh timers display <titre ...> {ci}: affiche un compteur dans le " +"scoreboard. Automatique au démarrage du compteur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "{cs}Le compteur {0}{cs} a été supprimé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "{cc}/uh timers remove <title ...> {ci}: supprime un compteur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "{cs}Le compteur {0}{cs} n'est plus en pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "" +"{cc}/uh timers resume <title ...> {ci}: redémarre un compteur après une " +"pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "{cs}La durée du compteur {0}{cs} est désormais {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or hh:mm:" +"ss." +msgstr "" +"{ce}La syntaxe de la durée entrée est invalide, les formats acceptés sont " +"mm, mm:ss ou hh:mm:ss." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a timer." +msgstr "" +"{cc}/uh timers set <durée> <titre ...> {ci}: modifie la durée d'un compte à " +"rebours." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "{ce}Un compteur nommé {0}{ce} existe déjà, choisissez un autre nom." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "{cs}Le compteur {0}{cs}, de durée {1}, a bien été enregistré." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "" +"{cc}/uh timers add <durée> <titre ...> {ci}: ajoute un compte à rebours." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "{cs}Le compteur {0}{cs} est désormais en pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "{cc}/uh timers pause <titre ...> {ci}: met en pause un comparateur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:61 +msgid "{ce}You cannot load unknown players in offline mode, sorry." +msgstr "" +"{ce}Vous ne pouvez pas charger des joueurs inconnus en mode hors-ligne, " +"désolé." + +#. Error returned if one calls /uh loadplayers without arguments. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:68 +msgid "{ce}You need to provide at least one player name." +msgstr "{ce}Vous devez spécifier au moins un nom de joueur." + +#. Message displayed when the /uh loadplayers command is used, as the execution may take some time. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:73 +msgid "{cst}Loading players..." +msgstr "{cst}Chargement des joueurs..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:80 +msgid "{cs}Loaded {0} player successfully." +msgid_plural "{cs}Loaded {0} players successfully." +msgstr[0] "{cs}{0} joueur a été chargé." +msgstr[1] "{cs}{0} joueurs ont été chargés." + +#. Message sent if some players cannot be loaded while /uh loadplayers is used. 0 = amount of players missing; 1 = list of nicknames (format "nick1, nick2, nick3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:88 +msgid "{ce}{0} player is missing: {1}." +msgid_plural "{ce}{0} players are missing: {1}." +msgstr[0] "{ce}Il manque {0} joueur : {1}." +msgstr[1] "{ce}Il manque {0} joueurs : {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHLoadPlayersCommand.java:108 +msgid "" +"{cc}/uh loadplayers <pseudo> [pseudo] ... {ci}: loads the given players in " +"the server so they can be added to teams even if they never logged in." +msgstr "" +"{cc}/uh loadplayers <pseudo> [pseudo] ... {ci}: charges les joueurs " +"spécifiés afin qu'il puissent être ajoutés dans une équipe même s'ils ne se " +"sont jamais connectés au serveur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "{cst}Vous avez été immobilisé(e) par {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "{cst}Vous avez été libéré(e) par {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "{cs}{0} est désormais immobilisé(e)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "{cs}{0} est désormais libéré(e)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "{darkaqua}Le jeu est désormais en pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "{darkaqua}Le jeu n'est plus en pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "{aqua}------ Commandes liées à l'immobilisation ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "" +"{cc}/uh freeze on [joueur] {ci}: immobilise un joueur, ou l'exécuteur sans " +"joueur spécifié." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if " +"the entire game is frozen." +msgstr "" +"{cc}/uh freeze off [player] {ci}: libère un joueur (ou l'envoyeur), même si " +"le jeu est en pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "" +"{cc}/uh freeze all {ci}: met le jeu en pause (immobilise les joueurs, mobs, " +"et le compteur)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this " +"in order to relaunch the timer." +msgstr "" +"{cc}/uh freeze none {ci}: relance le jeu. Vous DEVEZ exécuter ceci pour " +"relancer le compteur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "" +"{cc}/uh freeze {ci}: (dés)immobilise l'ensemble du jeu, ou un joueur. " +"Consultez /uh freeze pour plus de détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "{ce}Ce joueur n'est pas connecté." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "" +"{ce}Vous ne pouvez pas tuer un joueur avec cette commande, pour éviter toute " +"faute de frappe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "" +"{cc}/uh heal <joueur> [demi-coeurs=20|±diff] {ci}: change la vie d'un joueur " +"avec le nombre de demi-coeurs donné (par défaut, 20)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" +"{cc}/uh feed <joueur> [faim=20] [saturation=max] {ci}: nourrit un joueur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "{ce}Cette personne n'a jamais été vue sur le serveur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "{cs}Le joueur {0} est désormais marqué comme mort." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "{ce}{0} n'est pas un joueur vivant." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "" +"{cc}/uh kill <joueur> {ci}: marque un joueur comme mort, même s'il est hors-" +"ligne." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:99 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the " +"game." +msgstr "" +"{ce}Le jeu est déjà démarré ! Rechargez ou redémarrez le serveur pour " +"redémarrer." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:133 +msgid "{aqua}------ Beginning of the game ------" +msgstr "{aqua}------ Démarrage du jeu ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:134 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "{cc}/uh start {ci}: démarre le jeu, tout simplement." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:135 +msgid "{aqua}Startup options" +msgstr "{aqua}Options de démarrage" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:136 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append " +"them to the command with spaces." +msgstr "" +"{ci}Vous pouvez ajouter des options pour changer la manière dont le jeu est " +"démarré. Pour ce faire, ajoutez les tags suivant après la commande (séparés " +"par des espaces)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:137 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "" +"{cc}slow:true {ci}: lance le jeu doucement, en deux étapes (téléportation " +"puis commencement), pour les plus petits serveurs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:138 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "" +"{cc}ignoreTeams:true {ci}: même avec des équipes, téléporte les joueurs " +"comme pour un jeu solo (uniquement un joueur par point de démarrage, et non " +"un point par équipe)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:145 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "" +"{cc}/uh start {ci}: lance le jeu. Consultez /uh start help pour les options " +"de démarrage (lent, en ignorant les équipes)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:109 +msgid "{cs}The player {0} is now a spectator." +msgstr "{cs}Le joueur {0} est désormais un spectateur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ce}The player {0} was not found." +msgstr "{ce}Le joueur {0} n'a pas été trouvé." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgid "{cs}The player {0} is now a player." +msgstr "{cs}Le joueur {0} est désormais un joueur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:144 +msgid "{ce}There isn't any spectator to list." +msgstr "{ce}Il n'y a pas de spectateur à lister." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:148 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "{ci}{0} spectateur enregistré." +msgstr[1] "{ci}{0} spectateurs enregistrés." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:149 +msgid "{ci}This count includes only the initial spectators." +msgstr "{ci}Ce compte inclue uniquement les spectateurs initiaux." + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:154 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "{lightpurple} - {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:191 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "{aqua}------ Commandes liées aux spectateurs initiaux ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:193 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "{cc}/uh spec add <joueur> {ci}: ajoute un spectateur initial." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:194 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "{cc}/uh spec remove <joueur> {ci}: supprime un spectateur initial." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:195 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "{cc}/uh spec list {ci}: liste les spectateurs initiaux." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:203 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "" +"{cc}/uh spec {ci}: gère les spectateurs. Exécutez /uh spec pour plus de " +"détails." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "{ce}Aucune règle n'est enregistrée dans le fichier de configuration." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "{cs}Les règles ont été envoyées à {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" +"{ce}Impossible d'afficher les règles à {0} car il ou elle est hors-ligne." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" +"{cc}/uh rules [joueur] {ci}: envoie les règles du jeu au serveur ou au " +"joueur spécifié." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "{cs}Vous discutez désormais avec votre équipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "{cs}Vous discutez désormais avec tous le monde." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "{cs}Vous discutez désormais avec l'équipe {0}{cs}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed ..." +">{ci}." +msgstr "" +"{ci}Légende: {cc}/uh command <requis> [optionnel=valeur par défaut] <espaces " +"autorisées ...>{ci}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "{ce}{bold}Vous ne pouvez exécuter cette commande ainsi." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "{ce}L'aide est rappelée ci-dessus." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "{ce}Vous n'avez pas le droit d'exécuter cette commande." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "{ce}Vous ne pouvez exécuter cela qu'en étant un joueur." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +msgid "{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "{ce}Vous êtes hors de la future bordure de {0} bloc de diamètre." +msgstr[1] "{ce}Vous êtes hors de la future bordure de {0} blocs de diamètre." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "{ce}Vous êtes hors de la future bordure de {0}×{0} blocs." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "{ci}Il vous reste {0} blocs à parcourir avant d'y être." +msgstr[1] "{ci}Il vous reste {0} bloc à parcourir avant d'y être." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:334 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "{ce}Impossible de démarrer : pas assez de points de téléportation." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:335 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" +"{ci}Vous pouvez utiliser {cc}/uh spawns generate <random|circular|grid>{ci} " +"pour automatiquement générer les points de téléportation manquant." + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:338 +msgid "Or" +msgstr "Ou" + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:341 +msgid "click here" +msgstr "cliquez ici" + +#. In the sentence: "Or click here to generate the spawns randomly." +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:347 +msgid "to generate the spawns randomly." +msgstr "afin de générer les points de démarrage aléatoirement." + +#. A simple information, because this start is slower (yeah, Captain Obvious here) +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:479 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "{lightpurple}Téléportation en cours... Merci de patienter." + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "{lightpurple}Téléportation... {gray}({0}/{1})" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:514 +msgid "{gray}Player {0}{gray} teleported." +msgstr "{gray}Joueur {0}{gray} téléporté." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:573 +msgid "{cs}All teams are teleported." +msgstr "{cs}Toutes les équipes ont été téléportées." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:574 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "" +"{gray}Utilisez {cc}/uh start{gray} ou cliquez ici pour démarrer le jeu." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:575 +msgid "Click here to start the game" +msgstr "Cliquez ici pour démarrer la partie" + +#. Displayed in the action bar when the slow teleportation is finished but the game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:584 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "{lightpurple}Téléportation terminée. {gray}Ça ne devrait pas tarder..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:615 +msgid "{ce}Please execute {cc}/uh start slow:true{ce} before." +msgstr "{ce}Veuillez exécuter {cc}/uh start slow:true{ce} avant." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:621 +msgid "{ce}Please wait while the players are teleported." +msgstr "{ce}Veuillez patienter, les équipes sont en train d'être téléportées." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:717 +msgid "" +"{red}{bold}Warning!{white} The grace period ended, you are now vulnerable." +msgstr "" +"{red}{bold}Attention !{white} La période de grâce est terminée ; vous êtes " +"désormais vulnérable." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:736 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "{red}{bold}Attention !{white} Le PvP est désormais actif." + +#. Spectators list item if the nick cannot be found +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1073 +#, java-format +msgid "Unknown player with UUID {0}" +msgstr "Joueur inconnu ayant l'UUID {0}" + +#. The "and" in the winners players list (like "player1, player2 and player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1219 +msgctxt "winners_list" +msgid "and" +msgstr "et" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1231 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Félicitations à {0} (équipe {1}{green}) " +"pour leur victoire ! {darkgreen}{obfuscated}--" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1235 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Félicitation à {0} pour sa victoire ! " +"{darkgreen}{obfuscated}--" + +#. The main title of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1247 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1254 +msgid "{darkgreen}{0}" +msgstr "{darkgreen}{0}" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1249 +msgid "{green}This team wins the game!" +msgstr "{green}Cette équipe remporte la victoire !" + +#. The subtitle of the /title displayed when a player wins the game (in solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1256 +msgid "{green}wins the game!" +msgstr "{green}remporte la partie !" + +#~ msgid "" +#~ "{ce}Unable to add the player {0} to the team {1}. This player is unknown " +#~ "in the server." +#~ msgstr "" +#~ "{ce}Impossible d'ajouter le joueur {0} dans l'équipe {1}. Ce joueur n'est " +#~ "jamais venu sur ce serveur." + +#~ msgid "Spawn point {0},{1} added from the config file" +#~ msgstr "" +#~ "Point de démarrage {0},{1} ajouté depuis le fichier de configuration." + +#~ msgid "Invalid spawn point set in config: {0}" +#~ msgstr "Point de démarrage invalide dans la configuration : {0}" + +#~ msgid "Invalid team set in config: {0}" +#~ msgstr "Équipe invalide dans la configuration : {0}" + +#~ msgid "Team {0} ({1}) added from the config file" +#~ msgstr "Équipe {0} ({1}) ajoutée depuis le fichier de configuration." + +#~ msgid "Team {0} added from the config file" +#~ msgstr "Équipe {0} ajoutée depuis le fichier de configuration." diff --git a/src/main/resources/i18n/fr_FR.yml b/src/main/resources/i18n/fr_FR.yml deleted file mode 100644 index b861147..0000000 --- a/src/main/resources/i18n/fr_FR.yml +++ /dev/null @@ -1,507 +0,0 @@ -author: "Amaury Carrade" -keys: - load: - spawnPointAdded: "Point de démarrage {0},{1} ajouté depuis le fichier de configuration." - invalidSpawnPoint: "Point de démarrage invalide dans la configuration : {0}" - teamAdded: "Équipe {0} ajoutée depuis le fichier de configuration." - namedTeamAdded: "Équipe {0} ({1}) ajoutée depuis le fichier de configuration." - invalidTeam: "Équipe invalide dans la configuration : {0}" - recipeApple: "Recettes des pommes d'or ajoutées." - recipeCompass: "Recette du compas ajoutée." - recipeMelon: "Recette du melon scintillant ajoutée." - loaded: "Plugin Ultra Hardcore chargé." - - WBNotInstalled1: "{darkred}[UHC] {ce}WorldBorder pas installé : bordures non surveillées !" - WBNotInstalled2: "{gray}Aussi, sans WorldBorder, impossible de réduire la bordure pendant le jeu (sauf avertissements)." - WBNotInstalled3: "{gray}Installez le plugin ; UHPlugin va automatiquement le configurer." - - SPNotInstalled1: "{darkred}[UHC] {ce}SpectatorPlus n'est pas installé." - SPNotInstalled2: "{gray}Si vous voulez un mode spectateur, installez le plugin ; UHPlugin va automatiquement le configurer." - - PLNotInstalled1: "{darkred}[UHC] {ce}ProtocolLib est requis mais non installé !" - PLNotInstalled2: "{gray}Les options suivantes requièrent la présence de ProtocolLib :" - PLNotInstalledItem: "{darkgray} - {gray}{0}" - PLNotInstalled3: "{gray}ProtocolLib est disponible ici : {0}" - - cmd: - errorLoad: "{ce}Une erreur est survenue, consultez la console pour plus de détails. Il s'agit probablement d'un bug." - errorUnknown: "{ce}Cette commande n'existe pas. Tapez /uh pour la liste des commandes." - errorUnauthorized: "{ce}Vous n'avez pas le droit d'exécuter cette commande." - - titleHelp: "{yellow}{0} - version {1}" - legendHelp: "{ci}Légende: {cc}/uh command <requis> [optionnel=valeur par défaut] <espaces autorisées ...>{ci}." - helpNextPage: "{gray}Page suivante : /uh {0}" - - titleGameCmd: "{aqua}------ Commandes liées au jeu ------" - helpStart: "{cc}/uh start {ci}: lance le jeu." - helpStartSlow: "{cc}/uh start slow {ci}: lance le jeu doucement, en deux étapes, pour les plus petits serveurs." - helpShift: "{cc}/uh shift {ci}: passe un épisode." - helpTeam: "{cc}/uh team {ci}: gère les équipes. Exécutez /uh team pour plus de détails." - helpSpawns: "{cc}/uh spawns {ci}: gère les points de démarrage. Exécutez /uh spawns pour plus de détails." - helpSpec: "{cc}/uh spec {ci}: gère les spectateurs. Exécutez /uh spec pour plus de détails." - helpWall: "{cc}/uh generatewalls {ci}: génère les murs suivant la configuration." - helpBorder: "{cc}/uh border {ci}: gère la bordure. Exécutez /uh border pour plus de détails." - - titleBugCmd: "{aqua}------ Commandes liées aux bugs ------" - helpHeal: "{cc}/uh heal <joueur> [demi-coeurs=20|±diff] {ci}: change la vie d'un joueur avec le nombre de demi-coeurs donné (par défaut, 20)." - helpHealall: "{cc}/uh healall [demi-coeurs=20|±diff] {ci}: change la vie de tous les joueurs, et non d'un seul." - helpFeed: "{cc}/uh feed <joueur> [faim=20] [saturation=max] {ci}: nourrit un joueur." - helpFeedall: "{cc}/uh feedall [faim=20] [saturation=max] {ci}: nourrit tous les joueurs." - helpKill: "{cc}/uh kill <joueur> {ci}: marque un joueur comme mort, même s'il est hors-ligne." - helpResurrect: "{cc}/uh resurrect <joueur> {ci}: fait revivre un joueur." - helpTpback: "{cc}/uh tpback <joueur> [force] {ci}: téléporte un joueur au lieu de sa mort en toute sécurité." - - titleMiscCmd: "{aqua}------ Commandes diverses ------" - helpFreeze: "{cc}/uh freeze {ci}: (dés)immobilise l'ensemble du jeu, ou un joueur. Consultez /uh freeze pour plus de détails." - helpFinish: "{cc}/uh finish {ci}: affiche le nom du/des vainqueurs et lance des feux d'artifices." - helpTP: "{cc}/uh tp {ci}: téléporte les spectateurs ou une équipe. Consultez /uh tp pour plus de détails." - helpTimers: "{cc}/uh timers {ci}: gère les comptes à rebours. Consultez /uh timers pour plus de détails." - helpInfos: "{cc}/uh infos {ci}: affiche des informations à propos du jeu en cours." - helpAbout: "{cc}/uh about {ci}: informations à propos du plugin et des traductions." - - teamHelpTitle: "{aqua}------ Commandes liées aux équipes ------" - teamHelpAdd: "{cc}/uh team add <couleur> {ci}: ajoute une équipe de la couleur donnée." - teamHelpAddName: "{cc}/uh team add <couleur> <nom ...> {ci}: ajoute une équipe avec le nom et la couleur donnés." - teamHelpRemove: "{cc}/uh team remove <nom ...> {ci}: supprime une équipe." - teamHelpJoin: "{cc}/uh team join <joueur> <nomÉquipe ...> {ci}: ajoute un joueur dans l'équipe donnée. Le nom de l'équipe est sa couleur, ou le nom explicite donné." - teamHelpLeave: "{cc}/uh team leave <joueur> {ci}: retire un joueur de son équipe." - teamHelpList: "{cc}/uh team list {ci}: liste toutes les équipes et leurs membres." - teamHelpReset: "{cc}/uh team reset {ci}: supprime toutes les équipes." - teamHelpJoinCmd: "{cc}/join [joueur] <équipe ...> {ci}: ajoute “joueur” (ou l'envoyeur) dans l'équipe donnée. Sans argument, affiche le sélecteur d'équipe." - teamHelpLeaveCmd: "{cc}/leave [joueur] {ci}: retire “joueur” (ou l'envoyeur) de son équipe." - - spawnsHelpTitle: "{aqua}------ Commandes de gestion des points de démarrage ------" - spawnsHelpAdd: "{cc}/uh spawns add {ci}: ajoute un point de démarrage à la position de l'exécutant." - spawnsHelpAddXZ: "{cc}/uh spawns add <x> <z> {ci}: ajoute un point de démarrage aux coordonnées données, dans le monde principal." - spawnsHelpGenerate: "{cc}/uh spawns generate {ci}: génère automatiquement des points de démarrage. Consultez /uh spawns generate pour plus de détails." - spawnsHelpGenerateDetailsCmdTitle: "{aqua}Commande" - spawnsHelpGenerateDetailsCmd: "{cc}/uh spawns generate <circular|grid|random> [taille] [distanceMin] [nombre] [xCentre] [zCentre] [monde]" - spawnsHelpGenerateDetailsShapesTitle: "{aqua}Formes" - spawnsHelpGenerateDetailsShapesRandom: " - {cc}random{ci} : génère des points aléatoirement sur la carte, avec une distance minimale entre eux." - spawnsHelpGenerateDetailsShapesGrid: " - {cc}grid{ci} : génère les points sur des carrés concentriques, en commençant par le plus grand. La distance entre deux points est constante." - spawnsHelpGenerateDetailsShapesCircular: " - {cc}circular{ci}: génère les points sur des cercles concentriques, avec une distance minimale entre deux points. Sur chaque cercle, l'angle (et donc la distance) entre deux points est constant." - spawnsHelpGenerateDetailsArgsTitle: "{aqua}Arguments" - spawnsHelpGenerateDetailsArgsSize: " - {cc}taille{ci} : la taille de la région dans laquelle les points vont être générés. La région est carrée ou circulaire, selon la configuration. Par défaut : la taille de la carte." - spawnsHelpGenerateDetailsArgsDistanceMin: " - {cc}distanceMin{ci} : la distance minimale entre deux points. Par défaut : 250 blocs." - spawnsHelpGenerateDetailsArgsCount: " - {cc}nombre{ci} : le nombre de points à générer. Par défaut : le nombre de joueurs ou d'équipes." - spawnsHelpGenerateDetailsArgsCenter: " - {cc}xCentre{ci}, {cc}zCentre{ci} : le centre de la région dans laquelle les points sont générés. Par défaut : le point d'apparition du monde." - spawnsHelpGenerateDetailsArgsWorld: " - {cc}monde{ci} : le monde dans lequel les points seront générés." - spawnsHelpList: "{cc}/uh spawns list {ci}: liste les points de démarrage enregistrés." - spawnsHelpDump: "{cc}/uh spawns dump {ci}: affiche les points de démarrage dans un format exportable. {gray}Utilisez ceci pour afficher les points sur un graph, par exemple." - spawnsHelpRemove: "{cc}/uh spawns remove [<x> <z>] {ci}: supprime les points de démarrage aux coordonnées spécifiées, ou à la position de l'envoyeur sans coordonnées." - spawnsHelpReset: "{cc}/uh spawns reset {ci}: supprime tous les points de démarrage enregistrés." - - specHelpTitle: "{aqua}------ Commandes liées aux spectateurs initiaux ------" - specHelpNoticeSpectatorPlusNotInstalled: "{ce}Attention{ci}: SpectatorPlus n'étant pas installé, un spectateur n'est qu'un joueur ignoré." - specHelpAdd: "{cc}/uh spec add <joueur>{ci}: ajoute un spectateur initial." - specHelpRemove: "{cc}/uh spec remove <joueur>{ci}: supprime un spectateur initial." - specHelpList: "{cc}/uh spec list{ci}: liste les spectateurs initiaux." - - specHelpTitle: "{aqua}------ Commandes liées à l'immobilisation ------" - freezeHelpOn: "{cc}/uh freeze on [joueur]{ci}: immobilise un joueur, ou l'exécuteur sans joueur spécifié." - freezeHelpOff: "{cc}/uh freeze off [player]{ci}: libère un joueur (ou l'envoyeur), même si le jeu est en pause." - freezeHelpAll: "{cc}/uh freeze all{ci}: met le jeu en pause (immobilise les joueurs, mobs, et le compteur)." - freezeHelpNone: "{cc}/uh freeze none{ci}: relance le jeu. Vous DEVEZ exécuter ceci pour relancer le compteur." - - borderHelpTitle: "{aqua}------ Commandes liées aux bordures ------" - borderHelpCurrent: "{cc}/uh border current{ci}: retourne la taille actuelle de la carte." - borderHelpSet: "{cc}/uh border set <diamètre> [force]{ci}: change la taille de la carte. Si le paramètre “force” n'est pas donné, l'opération sera annulée s'il existe des joueurs hors de la bordure." - borderHelpWarning: "{cc}/uh border warning <futurDiamètre> [minutesAvantRéduction]{ci}: avertit tous les joueurs hors de la future bordure donnée. Ce n'est qu'un avertissement, rien de plus." - borderHelpWarningCancel: "{cc}/uh border warning cancel{ci}: annule un précédent avertissement." - borderHelpCheck: "{cc}/uh border check <diamètre>{ci}: retourne la liste des joueurs hors de la bordure." - - tpHelpTitle: "{aqua}------ Commandes de téléportation ------" - tpHelpTeam: "{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: téléporte une équipe au lieu ou au joueur indiqué." - tpHelpSpectators: "{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: téléporte les spectateurs (i.e. les joueurs non-vivants) au lieu ou au joueur indiqué." - - timersHelpTitle: "{aqua}------ Commandes liées aux comptes à rebours ------" - timersHelpAdd: "{cc}/uh timers add <durée> <titre ...> {ci}: ajoute un compte à rebours." - timersHelpSet: "{cc}/uh timers set <durée> <titre ...> {ci}: modifie la durée d'un compte à rebours." - timersHelpDisplay: "{cc}/uh timers display <titre ...> {ci}: affiche un compteur dans le scoreboard. Automatique au démarrage du compteur." - timersHelpHide: "{cc}/uh timers hide <titre ...> {ci}: retire un compteur du scoreboard. N'arrête pas le compteur." - timersHelpStart: "{cc}/uh timers start <titre ...> {ci}: démarre un compte à rebours." - timersHelpPause: "{cc}/uh timers pause <titre ...> {ci}: met en pause un comparateur." - timersHelpResume: "{cc}/uh timers resume <title ...> {ci}: redémarre un compteur après une pause." - timersHelpStop: "{cc}/uh timers stop <title ...> {ci}: force l'arrêt d'un compteur. Il est retiré du scoraboard." - timersHelpRemove: "{cc}/uh timers remove <title ...> {ci}: supprime un compteur." - timersHelpList: "{cc}/uh timers list {ci}: liste les compteurs enregistrés." - timersHelpDurations: "{gray}Format des durées : mm, mm:ss ou hh:mm:ss." - - about: - authors: "Plugin réalisé avec amour par {0}." - and: "et" - - build: - number: "Numéro de construction : {0}." - notAvailable: "Numéro de construction indisponible." - - i18n: - title: "{aqua}------ Traductions ------" - selected: "Langue courante : {0} (traduit par {1})." - fallback: "Langue par défaut : {0} (traduit par {1})." - license: - title: "{aqua}------ Licence ------" - license: "Publié sous licence générale publique GNU (version 3)." - - start: - already: "{ce}Le jeu est déjà démarré ! Rechargez ou redémarrez le serveur pour redémarrer." - syntax: "{ce}Erreur de syntaxe. Utilisation : /uh start [slow] ou /uh start slow go." - notEnoughTP: "{ce}Impossible de démarrer : pas assez de points de téléportation." - teleportationInProgress: "{lightpurple}Téléportation en cours... Merci de patienter." - - startSlowBeforeStartSlowGo: "{ce}Veuillez exécuter {cc}/uh start slow{ce} avant." - startSlowWaitBeforeGo: "{ce}Veuillez patienter, les équipes sont en train d'être téléportées." - startSlowTeamTP: "{gray}Équipe {0}{gray} téléportée." - startSlowAllTeamsTP: "{cs}Toutes les équipes ont été téléportées." - startSlowAllTeamsTPCmd: "{gray}Utilisez {cc}/uh start slow go{gray} pour démarrer le jeu." - - go: "{green}--- GO ---" - - finish: - notStarted: "{ce}Le jeu n'est pas encore démarré !" - notFinished: "{ce}Il n'y a pas qu'une équipe encore en vie !" - - and: "et" - - broadcast: - withTeams: "{darkgreen}{obfuscated}--{green} Félicitations à {0} (équipe {1}{green}) pour leur victoire ! {darkgreen}{obfuscated}--" - withoutTeams: "{darkgreen}{obfuscated}--{green} Félicitation à {0} pour sa victoire ! {darkgreen}{obfuscated}--" - - episodes: - end: "{aqua}-------- Fin de l'épisode {0} --------" - endForced: "{aqua}-------- Fin de l'épisode {0} [forcé par {1}] --------" - - scoreboard: - episode: "{gray}Épisode {white}{0}" - players: "{white}{0}{gray} joueurs" - teams: "{white}{0}{gray} équipes" - timer: "{white}{0}{gray}:{white}{1}" - timerWithHours: "{0}{gray}:{white}{1}{gray}:{white}{2}" - - motd: - beforeStart: "En attente de joueurs..." - starting: "Démarrage en cours..." - runningSolo: "Partie en cours ! {0} joueurs encore en vie." - runningTeams: "Partie en cours ! {0} joueurs en vie dans {1} équipes." - finishedSolo: "Partie terminée ; félicitation à {0} pour sa victoire !" - finishedTeams: "Partie terminée ; l'équipe {0} remporte la victoire !" - - death: - kickMessage: "jayjay" - banMessage: "Vous êtes mort !" - teamHasFallen: "{0}L'équipe {1} est vaincue !" - - canRespawn: "{darkpurple}{obfuscated}----{lightpurple}{italic} VOUS POUVEZ REVENIR{lightpurple}, cliquez sur {italic}Ressusciter {lightpurple}sur l'écran suivant." - - craft: - goldenApple: - loreLine1Player: "Fabriquée depuis la tête tranchée" - loreLine2Player: "de {0}" - loreLine1Monster: "Fabriquée depuis la tête tranchée" - loreLine2Monster: "d'un monstre maléfique" - - nameGoldenAppleFromHeadNormal: "{aqua}Tête d'or" - nameGoldenAppleFromHeadNotch: "{lightpurple}Tête d'or" - - compass: - noRottenFlesh: "{gray}{italic}Vous n'avez pas de chair de zombie." - nothingFound: "{gray}{italic}Seul le silence comble votre requête." - success: "{gray}Le compas pointe désormais vers le joueur le plus proche." - - dynmap: - markerLabelDeath: "Ici disparu {0}" - markerLabelSpawn: "Lieu de démarrage de l'équipe {0}" - markerLabelSpawnNoTeam: "Lieu de démarrage de {0}" - - wall: - startGen: "{cst}Génération des murs en cours..." - consoleDefaultWorld: "{ci}Depuis la console, génération du mur du monde par défaut, {0}" - error: "{ce}Impossible de générer le mur: voir logs pour plus de détails. Les blocs configurés sont probablement invalide." - unknownError: "{ce}Une erreur s'est produite, consultez la console pour plus de détails." - blocksError: "Impossible de construire le mur, les blocs configurés sont invalides." - done: "{cst}Génération terminée." - - spawns: - NaN: "{ce}Ceci n'est pas un nombre !" - syntaxError: "{ce}Erreur de syntaxe ; consultez /uh spawns." - errorCoords: "{ce}Vous devez spécifier les coordonnées depuis la console." - error2Coords: "{ce}Vous devez spécifier deux coordonnées." - - add: - added: "{cs}Point de démarrage ajouté dans le monde {0} : {1};{2}" - outOfLimits: "{ce}Vous ne pouvez pas ajouter un point de démarrage hors des bordures." - noSafeSpot: "{ce}Impossible d'ajouter ce point de démarrage : aucun endroit sûr trouvé dans le Nether." - - assumptions: - solo: "{ci}Aucune équipe trouvée : le jeu est considéré comme solo." - partialSolo: "{ci}Certains joueurs ne sont pas dans une équipe ; leur nombre a été ajoutés aux points de démarrage à générer." - - generate: - nothingToDo: "{ci}Vous avez demandé de ne rien générer. Rien ne sera généré." - unsupportedMethod: "{ce}La méthode de génération « {0} » n'est actuellement pas supportée." - unknownWorld: "{ce}Le monde {0} n'existe pas." - success: "{cs}Génération des points de démarrage effectuée avec succès." - impossible: "{ce}Vous avez demandé l'impossible : il y a trop de points sur une trop petite surface. Diminuez le nombre de points à générer ou la distance minimale entre deux points." - - list: - nothing: "{ce}Il n'y a pas de point de démarrage enregistré." - count: "{ci}Il y a {0} points de démarrage enregistrés." - world: "{lightpurple}Monde {0}" - item: - overworld: "{green}{0}{darkgreen};{green}{1}" - nether: "{red}{0}{darkred};{red}{1}" - end: "{yellow}{0}{gold};{yellow}{1}" - other: "{gray}{0}{darkgray};{gray}{1}" - - remove: - removed: "{cs}Le point de démarrage {1};{2} du monde {0} a été supprimé." - - reset: "{cs}Tous les points de démarrage ont été supprimés." - - team: - syntaxError: "{ce}Erreur de syntaxe, consultez /uh team." - unknownCommand: "{ce}Commande inconnue. Consultez /uh team pour obtenir la liste des commandes disponibles." - onlyAsAPlayer: "{ce}Cette commande ne peut être exécutée ainsi qu'en tant qu'un joueur." - - add: - errorColor: "{ce}Impossible d'ajouter l'équipe ; vérifiez le nom de la couleur. Conseil : utilisez l'autocomplétion." - errorExists: "{ce}Cette équipe existe déjà." - added: "{cs}Équipe {0}{cs} ajoutée." - - remove: - doesNotExists: "{ce}Cette équipe n'existe pas." - removed: "{cs}Équipe {0} supprimée." - - addplayer: - disconnected: "{ce}Impossible d'ajouter le joueur {0} dans l'équipe {1}. Ce joueur n'est jamais venu sur ce serveur." - success: "{cs}Le joueur {0} a été ajouté à l'équipe {1}{cs} avec succès." - added: "{aqua}Vous faites désormais partie de l'équipe {0}{aqua}." - doesNotExists: "{ce}Cette équipe n'existe pas." - full: "{ce}L'équipe {0}{ce} est pleine !" - - joinhelp: "{ce}Usage : {cc}/join [joueur] <équipe>{ce}." - - removeplayer: - disconnected: "{ce}Le joueur {0} est déconnecté et ne s'est jamais connecté au serveur auparavant !" - success: "{cs}Le joueur {0} a été retiré de son équipe avec succès." - removed: "{darkaqua}Vous ne faites plus partie de l'équipe {0}{darkaqua}." - - list: - nothing: "{ce}Il n'y a pas d'équipe à lister." - - itemTeam: "{0} ({1} joueurs)" - - bulletPlayerOnline: "{green} • " - bulletPlayerOffline: "{red} • " - - itemPlayer: "{0}" - - gui: - choose: "{gold}Cliquez ci-dessous pour rejoindre une équipe" - playersCount: "{gray}[{white}{0}{gray}/{white}{1}{gray}]" - playersCountUnlimited: "{gray}[{white}{0}{gray}]" - tooltipCount: "{0} joueur(s) dans cette équipe" - tooltipJoin: "Cliquez ici pour rejoindre l'équipe {0}" - tooltipJoinInside: "Vous êtes dans l'équipe {0}" - leaveTeam: "{darkred}[\u00D7] {red}Cliquez ici pour quitter votre équipe" - howToDisplayAgain: "{gray}Exécutez /join pour réafficher ceci" - noTeams: "{ce}Il n'y a aucune équipe disponible." - - reset: - success: "{cs}Toutes les équipes ont été supprimées." - - message: - noConsole: "{ce}Vous ne pouvez envoyer un message d'équipe depuis la console." - noTeam: "{ce}Vous n'êtes pas dans une équipe !" - usage: "{ce}Utilisation : /{0} <message>" - - notAllowed: - self: "{ce}Vous n'avez pas le droit d'envoyer des messages privés à votre équipe." - others: "{ce}Vous n'avez pas le droit d'entrer dans le chat privé d'une autre équipe." - - toggle: - nowTeamChat: "{cs}Vous discutez désormais avec votre équipe." - nowGlobalChat: "{cs}Vous discutez désormais avec tous le monde." - - nowOtherTeamChat: "{cs}Vous discutez désormais avec l'équipe {0}{cs}." - unknownTeam: "{ce}Cette équipe n'existe pas." - - format: "{gold}[{0}{gold} -> son équipe] {reset}{1}" - formatOtherTeam: "{gold}[{0}{gold} -> équipe {1}{gold}] {reset}{2}" - - infos: - notStarted: "{ci}Le jeu n'est pas encore démarré." - players: "{ci}{0} joueurs en vie, répartis dans {1} équipes." - - bulletOnline: "{green} • " - bulletOffline: "{red} • " - - separatorAliveState: "{gray} - " - - dead: "{red}mort" - alive: "{green}vivant" - - tooltips: - online: "Actuellement connecté(e)" - offline: "Actuellement hors-ligne" - - team: "Équipe : {0}" - - health: "{0} demi-cœurs" - - shift: - consoleName: "la console" - cantNotStarted: "{ce}Vous ne pouvez pas passer l'épisode actuel car le jeu n'a pas démarré." - - heal: - usage: "{ce}Utilisation : /uh heal <joueur> [nombre de demi-coeurs = 20]" - offline: "{ce}Ce joueur n'est pas connecté." - errorNaN: "{ce}Hey, ce n'est pas un nombre de demi-coeurs... C'est un texte... Pfff." - errorNoKill: "{ce}Vous ne pouvez pas tuer un joueur avec cette commande, pour éviter toute faute de frappe." - errorHealthNotUpdatedNoKill: "{ce}La vie de {0} n'a pas été changée, pour ne pas le/la tuer." - allErrorNoKill: "{ce}S'pèce de tueur en série !" - - feed: - usage: "{ce}Utilisation : /uh feed <joueur> [faim = 20] [saturation = max]" - offline: "{ce}Ce joueur n'est pas connecté." - errorNaN: "{ce}Les valeurs de faim et de saturation doivent être des nombres (possiblement à virgule pour la saturation) !" - - kill: - usage: "{ce}Utilisation : /uh kill <joueur>" - neverPlayed: "{ce}Cette personne n'a jamais été vue sur le serveur." - notAlive: "{ce}{0} n'est pas un joueur vivant." - killed: "{cs}Le joueur {0} est désormais marqué comme mort." - - resurrect: - usage: "{ce}Utilisation : /uh resurrect <joueur>" - unknownOrDead: "{ce}Ce joueur ne joue pas ou n'est pas mort !" - offlineOk: "{cs}Comme {0} est déconnecté, il sera ressuscité dés qu'il se connectera. S'il l'était, il n'est plus banni." - notDead: "{ce}{0} n'est pas mort !" - broadcastMessage: "{gold}{0} est revenu d'entre les morts !" - - tpback: - usage: "{ce}Utilisation : /uh tpback <joueur> [force]" - offline: "{ce}Le joueur {0} n'est pas connecté." - noDeathLocation: "{ce}Pas de localisation de mort enregistrée pour le joueur {0}." - teleported: "{cs}Le joueur {0} a été téléporté là où il est mort." - notTeleportedNoSafeSpot: "{ce}Le joueur {0} n'a PAS été téléporté car aucun point de téléportation sûr n'a été trouvé." - notTeleportedNoSafeSpotCmd: "{ci}Utilisez {cc}/uh tpback {0} force{ci} pour le téléporter malgré tout." - - tp: - NaN: "{ce}Les coordonnées doivent être trois nombres." - targetOffline: "{ce}{0} est hors-ligne !" - teamDoesNotExists: "{ce}Cette équipe n'est pas enregistrée." - - spectators: - syntaxError: "{ce}Erreur de syntaxe, consultez /uh spec." - unknownCommand: "{ce}Commande inconnue. Consultez /uh spec pour obtenir la liste des commandes." - offline: "{ce}Le joueur {0} n'est pas connecté." - - add: - success: "{cs}Le joueur {0} est désormais un spectateur." - - remove: - success: "{cs}Le joueur {0} est désormais un joueur." - - list: - nothing: "{ce}Il n'y a pas de spectateur à lister." - countSpectators: "{ci}{0} spectateur(s) enregistré(s)." - countOnlyInitial: "{ci}Ce compte inclue uniquement les spectateurs initiaux." - itemSpec: "{lightpurple} - {0}" - - freeze: - frozen: "{cst}Vous avez été immobilisé(e) par {0}." - unfrozen: "{cst}Vous avez été libéré(e) par {0}." - - playerFrozen: "{cs}{0} est désormais immobilisé(e)." - playerUnfrozen: "{cs}{0} est désormais libéré(e)." - - playerOnly: "{ce}Vous devez être un joueur pour exécuter cette commande ainsi." - offline: "{ce}{0} est hors-ligne !" - - scoreboard: "{darkaqua}En pause" - - broadcast: - globalFreeze: "{darkaqua}Le jeu est désormais en pause." - globalUnfreeze: "{darkaqua}Le jeu n'est plus en pause." - - borders: - syntaxError: "{ce}Erreur de syntaxe, consultez /uh border." - NaN: "{ce}“{0}” n'est pas un nombre..." - - current: - messageSquared: "{ci}La taille actuelle de la carte est {0}*{0}." - messageCircular: "{ci}La carte a actuellement un diamètre de {0} blocs." - - set: - playersOutsideCanceled: "{ce}Certains joueurs étant hors de cette nouvelle bordure, l'opération a été annulée." - playersOutsideCanceledCmd: "{ci}Utilisez {cc}/uh border set {0} force{ci} pour changer la taille de la carte malgré tout." - playersOutsideCanceledWarnWorldBorder: "{ce}ATTENTION: {ci}WorldBorder n'étant pas installé, les joueurs hors de la bordure ne seront pas téléportés !" - - broadcastSquared: "{lightpurple}La taille de la carte est désormais de {0}*{0}" - broadcastCircular: "{lightpurple}La carte a désormais un diamètre de {0} blocs." - - warning: - canceled: "{cs}Avertissement annulé." - - set: "{cs}Future taille enregistrée. Les joueurs hors de la bordure vont être avertis toutes les {0} secondes." - - messageSquared: "{ce}Vous êtes hors de la future bordure de {0}*{0} blocs." - messageCircular: "{ce}Vous êtes hors de la future bordure de {0} blocs de diamètre." - - messageDistance: "{ci}Il vous reste {0} blocs à parcourir avant d'y être." - messageDistanceTime: "{ci}Il vous reste {0} blocs à parcourir, et {1} minutes pour ce faire." - - nameTimer: "Réduction" - - timerUp: "{cs}Le temps imparti avant la nouvelle bordure est écoulé !" - - check: - allPlayersInside: "{cs}Tous les joueurs sont à l'intérieur de cette bordure." - countPlayersOutside: "{ci}Il y a {0} joueurs hors de cette bordure." - - itemPlayerFar: "{lightpurple} - {red}{0}{ci} (loin de la bordure)" - itemPlayerClose: "{lightpurple} - {yellow}{0}{ci} (proche de la bordure)" - itemPlayerVeryClose: "{lightpurple} - {green}{0}{ci} (très proche de la bordure)" - - timers: - syntaxError: "{ce}Erreur de syntaxe, consultez /uh timers." - durationSyntaxError: "{ce}La syntaxe de la durée entrée est invalide, les formats acceptés sont mm, mm:ss ou hh:mm:ss." - timerDoesNotExists: "{ce}Ce compteur n'est pas enregistré." - alreadyExists: "{ce}Un compteur nommé {0}{ce} existe déjà, choisissez un autre nom." - - added: "{cs}Le compteur {0}{cs}, de durée {1}, a bien été enregistré." - set: "{cs}La durée du compteur {0}{cs} est désormais {1}." - displayed: "{cs}Le compteur {0}{cs} est désormais affiché." - hidden: "{cs}Le compteur {0}{cs} est désormais masqué." - started: "{cs}Le compteur {0}{cs} a démarré." - paused: "{cs}Le compteur {0}{cs} est désormais en pause." - resumed: "{cs}Le compteur {0}{cs} n'est plus en pause." - stopped: "{cs}Le compteur {0}{cs} a été arrêté." - removed: "{cs}Le compteur {0}{cs} a été supprimé." - - list: - count: "{ci}Il y a {0} compteur(s) enregistré(s)." - itemRunning: "{green} • {ci}{0}{ci} - {1} secondes au total - {2}" - itemPaused: "{yellow} • {{ci}{0}{ci} - {1} secondes au total - {2}" - itemStopped: "{red} • {ci}{0}{ci} - {1} secondes au total" - - protips: - base: "{darkpurple}Astuce !" - - teamchat: - lock: "{gray}Verrouillez le chat d'équipe avec {cc}/togglechat{gray}, qui permet de passer d'un chat à l'autre." - useTCommand: "{gray}Vous pouvez envoyer un message à votre équipe avec {cc}/t <message>{gray}." - useGCommand: "{gray}Vous pouvez envoyer un message à tout le monde avec {cc}/g <message>{gray}." - - crafts: - goldenHead: "{gray}Vous pouvez fabriquer des pommes d'or avec les têtes (même recette avec une tête à la place de la pomme)." - compassEasy: "{gray}La boussole se fabrique avec dans les coins un os, une chaire de zombie, un œil d'araignée et une poudre à canon." - compassMedium: "{gray}La boussole se fabrique avec dans les coins un os, une chaire de zombie, un œil d'araignée et une poudre à canon ; au centre une Perle du Néant." - compassHard: "{gray}La boussole se fabrique avec dans les coins un os, une chaire de zombie, un œil d'araignée et une poudre à canon ; au centre un Œil du Néant." - glisteringMelon: "{gray}La pastèque scintillante se fabrique avec une pastèque et un bloc d'or." - noEnchGoldenApple: "{gray}La pomme d'or enchantée est désactivée pour cette partie." - - start: - invincibility: "{gray}Tombé(e) sur un arbre ? Sautez, il vous reste 25 secondes d'invincibilité." - diff --git a/src/main/resources/i18n/manifest.yml b/src/main/resources/i18n/manifest.yml deleted file mode 100644 index 31b7a08..0000000 --- a/src/main/resources/i18n/manifest.yml +++ /dev/null @@ -1,7 +0,0 @@ -version: 1.2 -languages: - - en_US - - fr_FR - - pt_PT - - pt_BR - - cs_CZ diff --git a/src/main/resources/i18n/pt_BR.po b/src/main/resources/i18n/pt_BR.po new file mode 100644 index 0000000..6ae3798 --- /dev/null +++ b/src/main/resources/i18n/pt_BR.po @@ -0,0 +1,2314 @@ +# Copyright or © or Copr. eraizel (2014 - 2016) +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: eraizel\n" +"POT-Creation-Date: 2016-01-20 03:37+0100\n" +"PO-Revision-Date: 2016-01-20 14:19:49.846513\n" +"Last-Translator: eraizel\n" +"Language-Team: eraizel\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. The name of the warning timer displaying the time left before the next +#. border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:84 +msgid "Border shrinking" +msgstr "Diminuindo a área" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:363 +msgid "{cs}All players are inside the given border." +msgstr "{cs}Todos os jogadores estão dentro das novas dimensões." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:367 +msgid "{ci}There are {0} players outside the given border." +msgstr "{ci}Existem {0} jogadores fora das novas dimensões." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:373 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "{lightpurple} - {red}{0}{ci} (Longe dos novas dimensões)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:377 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "{lightpurple} - {yellow}{0}{ci} (Perto dos novas dimensões)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:381 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "{lightpurple} - {green}{0}{ci} (Muito Perto dos novas dimensões)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{red}Warning!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{white}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:425 +msgid "{red}{bold}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:426 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "" +"{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "" +"{gray}Você pode digitar {cc}/togglechat{gray} para mudar e bloquear o chat " +"entre o chat de equipe e o chat global." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "" +"{gray}Para enviar mensagens rápidas para todos digite: {cc}/g " +"<mensagem>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "" +"{gray}Para enviar mensagens rápidas para a sua equipe digite: {cc}/t " +"<mensagem>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "" +"{gray}Você pode fazer maçãs douradas com cabeças (da mesma maneira que você " +"faria com uma maçã use a cabeça)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder." +msgstr "" +"{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, " +"um olho de aranha e uma pólvora." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an ender pearl." +msgstr "" +"{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, " +"um olho de aranha e uma pólvora; no centro, uma enderpearl." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "" +"{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, " +"um olho de aranha e uma pólvora; no centro, um olho de ender." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "" +"{gray}A melancia reluzente e feita com uma melancia e um bloco de ouro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "" +"{gray}As maçãs douradas encantadas (ou do capiroto) estão desativadas para " +"este jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "" +"{gray}Caiu em uma árvore? Pule, você ainda têm 25 segundos de " +"invencibilidade." + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:131 +msgid "{darkpurple}ProTip!" +msgstr "{darkpurple}Dica!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:204 +msgid "Ultra Hardcore plugin loaded." +msgstr "Plugin Ultra Difícil Carregado." + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:61 +msgid "{0} » {darkred}Delete" +msgstr "" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:69 +msgid "{green}Keep this team alive" +msgstr "" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:81 +msgid "{red}Delete this team {italic}forever" +msgstr "" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:68 +msgid "{0} » {black}Members" +msgstr "" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:77 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:123 +msgid "{green}« Go back" +msgstr "" + +#. The title of a button to select a player (a skull button). {0} = player's +#. display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:67 +msgid "Teams » {black}{0}" +msgstr "" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:73 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "" +msgstr[1] "" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{green}Update the color" +msgstr "" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:83 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:90 +msgid "{green}Rename the team" +msgstr "" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:92 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "{green} • " + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "{red} • " + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:106 +msgid "{green}Add or remove players" +msgstr "" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{red}Delete this team" +msgstr "" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:116 +msgid "{gray}Cannot be undone" +msgstr "" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:77 +msgid "{black}Select a team {reset}({0})" +msgstr "" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{white}Rename your team" +msgstr "" + +#. Warning displayed in the "Rename your team" button, if the player is not in +#. a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:91 +msgid "{gray}You have to be in a team" +msgstr "" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:100 +msgid "{white}New team" +msgstr "" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:118 +msgid "{blue}Players" +msgstr "" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "" + +#. Title of the team item in the teams selector GUI (with max). {0}: team +#. display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:177 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "" + +#. Title of the team item in the teams selector GUI (without max) {0}: team +#. display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:179 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "" +msgstr[1] "" + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "" + +#. The title of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "" + +#. The legend of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "" + +#. The summary title in the final « create the team » button of the create +#. team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "" + +#. The team name in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "" + +#. The team color in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "" + +#. The team members count in the final « create the team » button of the +#. create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:173 +msgid "{cs}Team created." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:177 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:118 +msgid "{ce}This team already exists." +msgstr "{ce}Esta equipe já existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:208 +#, java-format +msgid "Spawn point {0},{1} added from the config file" +msgstr "Local de spawn {0},{1} adicionado a partir das configurações" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:213 +#, java-format +msgid "Invalid spawn point set in config: {0}" +msgstr "Local de spawn inválido nas configurações: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:141 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:302 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "{aqua}Você foi adicionado à equipe {0}{aqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:335 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:369 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "{darkaqua}Você não faz mais parte da equipe {0}{darkaqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:84 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:211 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "{ce}Não lhe é permitido enviar mensagens privadas para a sua equipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:216 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "{ce}Não lhe é permitido entrar no chat privado de outra equipe." + +#. Format of a private team message from a team member. {0} = sender display +#. name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:99 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "{gold}[{0}{gold} -> equipe dele] {reset}{1}" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:105 +msgid "{ce}You are not in a team!" +msgstr "{ce}Você não pertence a nenhuma equipe!" + +#. Format of a private team message from a non-team-member. {0} = sender +#. display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:112 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "{gold}[{0}{gold} -> equipe {1}{gold}] {reset}{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:443 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:461 +#, java-format +msgid "Invalid team set in config: {0}" +msgstr "Equipe inválida nas configurações: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:450 +#, java-format +msgid "Team {0} ({1}) added from the config file" +msgstr "Equipe {0} ({1}) adicionada a partir das configurações" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:456 +#, java-format +msgid "Team {0} added from the config file" +msgstr "Equipe {0} adicionada a partir das configurações" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:497 +msgid "{gold}Click on the names below to join a team" +msgstr "{gold}Clique em um nome abaixo para se juntar a esta equipe" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. +#. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:511 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "{gray}[{white}{0}{gray}/{white}{1}{gray}]" + +#. Team count without max players (ex. [3]) followed in-game by the team name. +#. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:516 +msgid "{gray}[{white}{0}{gray}]" +msgstr "{gray}[{white}{0}{gray}]" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:534 +msgid "{0} ({red}dead{reset})" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:539 +msgid "{0} ({green}alive{reset})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:544 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "{0} jogador nesta equipe" +msgstr[1] "{0} jogadores nesta equipe" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = +#. team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:557 +#, java-format +msgid "You are in the team {0}" +msgstr "Você agora faz parte da equipe {0}" + +#. Tooltip on the chat team selector GUI when the player is not in the team. +#. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:562 +#, java-format +msgid "Click here to join the team {0}" +msgstr "Clique aqui para juntar-se à equipe {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:574 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "{darkred}[×] {red}Clique aqui para deixar esta equipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "{gray}Digite: /join para ver estas opções novamente" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "{ce}Não há nenhuma equipe disponível." + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:162 +msgid "jayjay" +msgstr "Ha! Ha! Levou uma Butinada!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:240 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "{0}Todos os jogadores da equipe {1} morreram!" + +#. A message displayed to the players under the death screen, about the +#. respawn possibility even if the death screen says the opposite (in hardcore +#. mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:284 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} Você pode " +"renascer{lightpurple}, clique em {italic}Renascer {lightpurple}na próxima " +"tela." + +#. The kick message displayed if a player tries to relog after his death and +#. it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:442 +msgid "You are dead!" +msgstr "Morreu :˜(" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:515 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "" +"{darkred}[UHC] {ce}WorldBorder não está instalado: muralhas não serão " +"verificadas!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:516 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game" +" (warnings excluded)." +msgstr "" +"{gray}Também, sem WorldBorder, as muralhas não poderão ser reduzidas durante" +" a partida (avisos excluidos)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:517 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "" +"{gray}Instale somente o plugin; o UHPlugin automaticamente o configurará." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:527 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "" +"{darkred}[UHC] {ce}ProtocolLib é obrigatório, porém, não está instalado!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:528 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "{gray}As seguintes opções requerem a presença do ProtocolLib:" + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = +#. option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:532 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "{darkgray} - {gray}{0}" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:545 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "{gray}ProtocolLib está disponivel aqui: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:673 +msgid "{cs}The timer before the new border is up!" +msgstr "{cs}Acabou o tempo para as novas dimensões!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:705 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "{aqua}-------- Fim do Episódio {0} [forcado por {1}] --------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:709 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "{aqua}-------- Fim do Episódio {0} --------" + +#. The title displayed when the episode change. {0} = new episode number; {1} +#. = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:721 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "" + +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:745 +msgid "{green}--- GO ---" +msgstr "{green}----- Começou! -----" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:753 +msgid "{darkgreen}Let's go!" +msgstr "" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:755 +msgid "{green}Good luck, and have fun" +msgstr "" + +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:887 +msgid "{gold}{0} returned from the dead!" +msgstr "{gold}{0} foi ressuscitado!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:200 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:279 +msgid "{aqua}Golden head" +msgstr "{aqua}Maçã Dourada" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:280 +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maçã Dourada" + +#. Error message if a player tries to use his pointing compass without rotten +#. flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:304 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "{gray}{italic}Para a bússola é necessária carne podre." + +#. Error message if a player tries to use his pointing compass without a +#. player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:335 +msgid "{gray}{italic}Only silence answers your request." +msgstr "{gray}{italic}Nenhum jogador encontrado nas proximidades." + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:342 +msgid "{gray}The compass now points to the closest player." +msgstr "{gray}A bússola está apotando para o jogador mais próximo de você." + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:152 +#, java-format +msgid "Death point of {0}" +msgstr "local onde {0} morreu" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:231 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "Local de spawn da equipe {0}" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation +#. ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:236 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:293 +#, java-format +msgid "Spawn point of {0}" +msgstr "Local de spawn de {0}" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +msgid "Made from the fallen head of a malignant monster" +msgstr "Feita da cabeça de um monstro malígno" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:290 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "Feita da cabeça de {0}" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:393 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Maçã Dourada" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:399 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maçã Dourada" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:426 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Maçã Dourada" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:432 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maçã Dourada" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:141 +msgid "{gray}Episode {white}{0}" +msgstr "{gray}Episódio {white}{0}" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:150 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:159 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "{white}{0}{gray} Jogador" +msgstr[1] "{white}{0}{gray} Jogadores" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:163 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "{white}{0}{gray} Equipe" +msgstr[1] "{white}{0}{gray} Equipes" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:205 +msgid "{bold}Your team" +msgstr "" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:278 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "" +msgstr[1] "" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:309 +msgid "{blue}{bold}Border" +msgstr "" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:317 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "" +msgstr[1] "" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:320 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "" +msgstr[1] "" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:336 +msgid "{white}{0} {1}" +msgstr "" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:341 +msgid "{gray}X: {white}{0} {1}" +msgstr "" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}Z: {white}{0} {1}" +msgstr "" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh +#. freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:384 +msgid "{darkaqua}Game frozen" +msgstr "{darkaqua}O jogo está congelado" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:121 +msgid "{red}{bold}Rules and informations" +msgstr "" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:132 +msgid "{darkgray}- {reset}{0}" +msgstr "" + +#. Episode in the player list ({episodeText} replacement). {0} = current +#. episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "Episode {0}" +msgstr "Episódio {0}" + +#. Players in the player list ({playersText} replacement). {0} = current alive +#. players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "{0} Jogador" +msgstr[1] "{0} Jogadores" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive +#. teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:121 +#, java-format +msgid "{0} team" +msgid_plural "{0} teams" +msgstr[0] "{0} Equipe" +msgstr[1] "{0} Equipes" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:89 +msgid "Waiting for players..." +msgstr "Aguardando jogadores..." + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:98 +msgid "Starting in progress..." +msgstr "Iniciando a partida..." + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:113 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "Partida em andamento! {0} jogador vivos." +msgstr[1] "Partida em andamento! {0} jogadores vivos." + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive +#. count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:118 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "Partida em andamento! {0} jogador vivos em {1} equipe." +msgstr[1] "Partida em andamento! {0} jogadores vivos em {1} equipes." + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:135 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "Partida encerrada! Parabéns ao jogador {0} pela sua vitória!" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:140 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "Partida encerrada! A equipe {0} foi a vencedora!" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "{0}{gray}:{white}{1}{gray}:{white}{2}" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "{white}{0}{gray}:{white}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "{aqua}------ Comandos do jogo ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "{aqua}------ Comandos para Bugs ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "{aqua}------ Outros Comandos ------" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:107 +msgid "{ce}Usage: /{0} <message>" +msgstr "{ce}Digite: /{0} <mensagem>" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "{aqua}------ Comandos para os Spawns ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "" +"{cc}/uh spawns {ci}: Gera os locais de spawn. Digite /uh spawns para " +"detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "{ce}As coordenadas precisam conter três números válidos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "{ce}Esta equipe não está registrada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "{ce}{0} não está online!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "{aqua}------ Comandos para Teletransporte ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" +"{cc}/uh tp team <x> <y> <z> | <objetivo> <equipe ...> {ci}: Teletransporta " +"uma equipe toda para um determinado local/objetivo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" +"{cc}/uh tp spectators <x> <y> <z> | <objetivo> {ci}: Teletransporta os " +"espectadores (ou seja, os jogadores mortos) para um determinado " +"local/objetivo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "" +"{cc}/uh tp {ci}: Teletransporta os espectadores ou uma equipe inteira. " +"Digite /uh tp para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "{yellow}{0} - versão {1}" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "e" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "Plugin feito com amor por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "Versão Número: {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "O número da versão não está disponível." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "{aqua}------ Traduções ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "Linguagem Selecionada: {0} (traduzido por {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "Linguagem Secundária: {0} (traduzido por {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "{aqua}------ Licença ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "Publicado sobre a CeCILL-B License." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "{cc}/uh about {ci}: Informação sobre o Plugin e as traduções." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:67 +msgid "{cs}Warning canceled." +msgstr "{cs}Alertas cancelados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:82 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "" +"{cs}Novas dimensões salvas. Todos os jogadores que estejam fora das novas " +"dimensões serão avisados a cada {0} segundo." +msgstr[1] "" +"{cs}Novas dimensões salvas. Todos os jogadores que estejam fora das novas " +"dimensões serão avisados a cada {0} segundos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:124 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "{ce}“{0}” não e um número..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" +"{cc}/uh border warning <tamanhofuturo> [minutos para a redução]{ci}: Informa" +" todos os jogadores que estão fora da futura área. É apenas um AVISO, nada " +"acontece." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "" +"{cc}/uh border warning cancel{ci}: Cancela os avisos da mudança na área de " +"jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "" +"{ce}Alguns jogadores estão fora da nova área. A operação foi cancelada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "" +"{ci}Digite: {cc}/uh border set {0} force{ci} para estabelecer uma nova " +"dimensão, mesmo que haja jogadores fora da área." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "" +"{ce}ATENÇÃO: {ci}O Plugin WorldBorder não está instalado, jogadores que " +"estejam fora da área não serão teletransportados!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:114 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "{lightpurple}A área atual do mapa circular e de {0} bloco." +msgstr[1] "{lightpurple}A área atual do mapa circular e de {0} blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:118 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "{lightpurple}A área atual do mapa quadrado é {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:149 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" +"{cc}/uh border set <tamanho> [force]{ci}: Muda o tamanho do mapa. Se o " +"comando force não for indicado, a operação será cancelada se houver algum " +"jogador fora da nova área." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "" +"{cc}/uh border check <tamanho>{ci}: Retorna uma lista dos jogadores que se " +"encontram fora da área especificada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "{ci}A área atual do mapa circular e de {0} bloco." +msgstr[1] "{ci}A área atual do mapa circular e de {0} blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "{ci}A área atual do mapa quadrado é {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "{cc}/uh border get{ci}: Informa o tamanho atual do mapa." + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "{ci}{0} jogador vivos em {1} equipe." +msgstr[1] "{ci}{0} jogadores vivos em {1} equipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "{ci}A partida não começou." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "Online neste momento" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "Offline neste momento" + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "Equipe: {0}" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "{gray} - " + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "{green}vivo" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "{0} meios-corações" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "{red}morto" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "{cc}/uh infos {ci}: Printa somente as informações sobre o jogo atual." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "" +"{ce}Pontos de alimentacão e saturacão precisam ser números (a saturacão em " +"fração, por exemplo: 2.2)!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "" +"{cc}/uh feedall [fome=20] [saturação=max] {ci}: Alimenta todos os jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "{cs}Local de spawn adicionado ao mundo {0}: {1};{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "{ce}Locais de spawn só são possíveis dentro das muralhas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "" +"{ce}Impossível adicionar este local de spawn: não foi encontrado um local " +"seguro no Inferno." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "{ce}É necessária a especificação de pelo menos duas coordenadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "{ce}Este não e um número!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "" +"{cc}/uh spawns add [<x> <z>]{ci}: Adiciona um local de spawn para uma equipe" +" ou jogador, no local onde é executado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "" +"{ci}Nenhuma equipe encontrada. Assumirei que o jogo está em modo solo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "" +"{ci}Alguns jogadores não estão em nenhuma equipe; este número foi adicionado" +" ao número de locais de spawn." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "{ce}O mundo {0} não existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "" +"{ci}Você especificou uma geração nula. Portanto, a geração está vazia." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "{ce}O método de geração “{0}” (ainda?) não foi implementado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "" +"{ce}A sua especificação é impossível: existem muitos locais de spawn em um " +"espaço limitado. Corrija este erro reduzindo o número de locais spawn ou o " +"espaço mínimo entre dois pontos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "{cs}Os Locais de spawn especificados foram gerados com sucesso." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "{aqua}Comandos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "{aqua}Formatos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr "" +" - {cc}random{ci}: Gera locais de spawn randomicos no mapa, com uma " +"distância mínima entre eles." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr "" +" - {cc}grid{ci}: Gera locais de spawn em forma de quadrados concêntricos, " +"com uma distância constante entre dois pontos gerados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" +" - {cc}circular{ci}: Gera locais de spawn em forma de círculos concêntricos," +" com uma distância constante entre dois pontos gerados. Em cada círculo, o " +"ângulo (e a distância) entre dois locais de spawn é constante." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "{aqua}Argumentos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr "" +" - {cc}size{ci}: É o tamanho da região onde os locais de spawn serão " +"gerados. Quadrado ou circular, seguindo o formato do mapa. O padrão é o " +"tamanho do mapa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr "" +" - {cc}distanceMin{ci}: É a distância mínima entre dois locais de spawn. " +"Padrão: 250 blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr "" +" - {cc}count{ci}: É o número de locais de spawn a serem gerados. Padrão: o " +"número de jogadores ou de equipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: O centro da região onde os pontos são " +"gerados. Padrão: o local de spawn do mundo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr " - {cc}world{ci}: O mundo onde os locais de spawn serão gerados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "" +"{cc}/uh spawns generate {ci}: Automaticamente gera locais de spawn. Digite: " +"/uh spawns generate para mais detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "" +"{cc}/uh spawns dump {ci}: Mostra os locais de spawn em um formato " +"exportável. {gray}Podendo ser utilizados em alguns sites para ver os locais " +"de spawn por exemplo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "{ce}Não existe nenhum local de spawn registrado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "{ci}Existem {0} locais de spawn registrados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "{lightpurple}Mundo {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:180 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "{cc}/uh spawns list {ci}: Lista dos locais de spawn registrados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "{cs}Todos os locais de spawn foram removidos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "" +"{cc}/uh spawns reset {ci}: Remove todos os locais de spawn registrados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "{cs}O local de spawn {1};{2} no mundo {0} foi removido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" +"{cc}/uh spawns remove [<x> <z>] {ci}: Remove coordenadas de spawn inseridas," +" ou o local onde o comando é executado se não forem inseridas coordenadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:110 +msgid "{ce}The player {0} is not online." +msgstr "{ce}{0} não está online." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "{ce}O jogador {0} não possui um local de morte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "{cs}O jogador {0} foi teletransportado para o local da sua morte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "" +"{ce}O jogador {0} não foi teletransportado porque não foi encontrado um " +"local seguro para esta operação." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" +"{ci}Digite: {cc}/uh tpback {0} force{ci} para teletransportar o jogador " +"mesmo que o local não seja seguro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "" +"{cc}/uh tpback <jogador> [force] {ci}: Teletransporta em segurança um " +"jogador para o local da sua morte. Quando especificado - force - " +"teletransporta o jogador mesmo que não seja seguro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "{ce}A partida ainda não iniciou!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "{ce}Não há nenhuma equipe viva!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "" +"{cc}/uh finish {ci}: Exibe o nome do(s) vencedor(es) e lança foguetes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this" +" point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his" +" spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "{ce}Este jogador não está jogando ou já se encontra morto!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "" +"{cs}Porque {0} está desconectado, quando ele ficar online será resuscitado. " +"Se estava banido, ja não está." + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "{ce}{0} não está morto!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "{cc}/uh resurrect <jogador> {ci}: Ressuscita o jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:111 +msgid "" +"{ce}Unable to add the player {0} to the team {1}. This player is unknown in " +"the server." +msgstr "{ce}Impossível adicionar {0} à equipe {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:119 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "{ce}Esta equipe não existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:132 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "{cs}O jogador {0} foi adicionado com sucesso à equipe {1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:178 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" +"{cc}/uh team join <jogador> <equipe ...>{ci}: Adiciona um jogador a uma " +"equipe. O nome da equipe pode ser a cor ou o seu determinado nome." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "{cs}Todas as equipes foram removidas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "{cc}/uh team reset {ci}: Elimina todas as equipes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "" +"{ce}Impossível criar a equipe, verifique a cor. Dica: use Tab para auto " +"completar." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:122 +msgid "{cs}Team {0}{cs} added." +msgstr "{cs}Equipe {0}{cs} adicionada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:164 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "" +"{cc}/uh team add <cor> [<nome ...>]{ci}: Adiciona uma equipe com uma " +"determinada cor." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:90 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "{ce}O jogador {0} está desconectado!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:107 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "{cs}O jogador {0} foi removido com sucesso de sua equipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:141 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "{cc}/uh team leave <jogador> {ci}: Retira um jogador da sua equipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "{cs}Equipe {0} removida." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "{cc}/uh team remove <nome ...> {ci}: Remove uma equipe" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "{ce}Não há nenhuma equipe para ser mostrada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "{0} ({1} jogador)" +msgstr[1] "{0} ({1} jogadores)" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "{cc}/uh team list {ci}: Lista das equipes e seus jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "{aqua}------ Comandos para a contagem de Tempo ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "" +"{cc}/uh timers {ci}: Configura os tempos. Digite /uh timers para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:106 +msgid "{aqua}------ Team commands ------" +msgstr "{aqua}------ Comandos para equipes ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:107 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the" +" given team. Without arguments, displays the chat-based team selector." +msgstr "" +"{cc}/join [player] <team ...> {ci}: Adiciona “jogador” (ou ele mesmo) para a" +" equipe determinada. Sem argumentos, apresenta opção escolher equipe via " +"chat (clicando na equipe)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:108 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "" +"{cc}/leave [player] {ci}: Remove o “jogador” (ou ele mesmo) de seu time." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:115 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "{cc}/uh team {ci}: Edita as equipes. Digite /uh team para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "{aqua}------ Comandos para área do jogo ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "" +"{cc}/uh border {ci}: Edita a área do jogo. Digite /uh border para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "{ce}Insira um número de meios-corações não um texto." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "{ce}Assassino!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "{ce}A vida de {0} não foi atualizada pois isso causaria a sua morte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "" +"{cc}/uh healall [meios-corações=20|±diferença] {ci}: Regenera todos os " +"jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "O console" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "" +"{ce}Não é possível passar para o próximo episódio porque o jogo ainda não " +"começou." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "{cc}/uh shift {ci}: Passa para o próximo episódio." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "{cst}Gerando as muralhas..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "{ci}A partir do console, gerando a área para o mundo padrão, {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the" +" config are probably invalid." +msgstr "" +"{ce}Impossível gerar a área: verifique os logs para detalhes. Os blocos " +"configurados são provavelmente inválidos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "{ce}Ocorreu um erro, verifique o console para maiores detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "{cst}Muralhas criadas com sucesso." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "" +"{cc}/uh generatewalls {ci}: Gera as muralhas, de acordo com as " +"configurações." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "{ce}Este cronômetro é inexistente." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "{cs}O cronômetro {0}{cs} foi interrompido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "" +"{cc}/uh timers stop <título ...> {ci}: Para um cronômetro. O cronômetro é " +"removido do placar." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "{cs}O cronômetro {0}{cs} foi iniciado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "{cc}/uh timers start <título ...> {ci}: Inicia um cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "{cs}O cronômetro {0}{cs} está ocultado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "" +"{cc}/uh timers hide <título ...> {ci}: Esconde um cronômetro do placar. Não " +"para o cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +#, fuzzy +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "{ci}Ao todo foram registrados {0} cronômetro." +msgstr[1] "{ci}Ao todo foram registrados {0} cronômetroes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{yellow} • {ci}{0}{ci} - total de {1} segundo - {2}" +msgstr[1] "{yellow} • {ci}{0}{ci} - total de {1} segundos - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:81 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{green} • {ci}{0}{ci} - total de {1} segundo - {2}" +msgstr[1] "{green} • {ci}{0}{ci} - total de {1} segundos - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:90 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "{red} • {ci}{0}{ci} - total de {1} segundo" +msgstr[1] "{red} • {ci}{0}{ci} - total de {1} segundos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:119 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "{cc}/uh timers list {ci}: Lista de todos os cronômetros registrados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "{cs}O cronômetro {0}{cs} está sendo exibido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard." +" Automatic when a timer is started." +msgstr "" +"{cc}/uh timers display <título ...> {ci}: Mostra um cronômetro no placar. " +"Automático quando um cronômetro e iniciado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "{cs}O cronômetro {0}{cs} foi removido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "{cc}/uh timers remove <título ...> {ci}: Remove um cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "{cs}O cronômetro {0}{cs} foi retomado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "" +"{cc}/uh timers resume <título ...> {ci}: Reinicia o cronômetro parado com o " +"comando pause." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "{cs}A duração do cronômetro {0}{cs} é agora de {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or " +"hh:mm:ss." +msgstr "" +"{ce}A duração inserida é inválida. Os formatos aceitáveis são mm ou mm:ss ou" +" hh:mm:ss." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a " +"timer." +msgstr "" +"{cc}/uh timers set <duração> <título ...> {ci}: Configura a duração de um " +"cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "" +"{ce}Um cronômetro com o nome {0}{ce} já existe; Por favor, renomeie o seu " +"cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "{cs}O cronômetro {0}{cs} (com duração {1}) foi adicionado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "" +"{cc}/uh timers add <duração> <título ...> {ci}: Adiciona um cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "{cs}O cronômetro {0}{cs} foi parado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "{cc}/uh timers pause <título ...> {ci}: Pausa um cronômetro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "{cst}Você foi congelado por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "{cst}Você foi descongelado por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "{cs}{0} está agora congelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "{cs}{0} está agora descongelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "{darkaqua}O jogo inteiro está congelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "{darkaqua}O jogo continua." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "{aqua}------ Comandos para Congelar ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "" +"{cc}/uh freeze on [jogador]{ci}: Congela um jogador, ou a si mesmo se o " +"jogador não for especificado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if" +" the entire game is frozen." +msgstr "" +"{cc}/uh freeze off [jogador]{ci}: Descongela um jogador, ou a si próprio, " +"mesmo com todo o jogo congelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "" +"{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "{cc}/uh freeze all{ci}: Congela o jogo todo (jogadores, mobs, tempo)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this" +" in order to relaunch the timer." +msgstr "" +"{cc}/uh freeze none{ci}: Descongela o jogo todo. Você DEVE executar este " +"comando para que o tempo do jogo volte a contar." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "" +"{cc}/uh freeze {ci}: (Des)congela o jogo todo, ou um jogador. Digite: /uh " +"freeze para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "{ce}Este jogador está desconectado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "" +"{ce}Não é permitido matar jogadores com este comando, isto pode causar " +"falhas na escrita." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "" +"{cc}/uh heal <jogador> [meios-corações=20|±diferença] {ci}: Regenera vida de" +" um jogador para os meios-corações indicados (padrão 20)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" +"{cc}/uh feed <jogador> [fome=20] [saturação=max] {ci}: Alimenta um jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "{ce}Este jogador não existe no servidor." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "{cs}O jogador {0} agora está morto." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "{ce}{0} não é um jogador vivo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "" +"{cc}/uh kill <player> {ci}: Assinala o jogador como morto, mesmo que ele " +"esteja desconecato." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:102 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the" +" game." +msgstr "" +"{ce}O jogo já comecou! Recarregue ou Reinicie o servidor para reiniciar o " +"jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:150 +msgid "{aqua}------ Beginning of the game ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:151 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:152 +msgid "{aqua}Startup options" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:153 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append" +" them to the command with spaces." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:154 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:155 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:162 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "{cc}/uh start {ci}: Inicia o jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:94 +msgid "{cs}The player {0} is now a spectator." +msgstr "{cs}O jogador {0} está agora em modo espectador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:115 +msgid "{cs}The player {0} is now a player." +msgstr "{cs}Modo espectador desativado para {0}, agora ele e um jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:125 +msgid "{ce}There isn't any spectator to list." +msgstr "{ce}Não há nenhum espectador para ser listado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "{ci}{0} Espectador registrado." +msgstr[1] "{ci}{0} Espectadores registrados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:130 +msgid "{ci}This count includes only the initial spectators." +msgstr "{ci}Este número inclui apenas os espectadores iniciais." + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "{lightpurple} - {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:171 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "{aqua}------ Comandos iniciais para Espectadores ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:173 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "{cc}/uh spec add <jogador>{ci}: Adiciona um espectador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:174 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "{cc}/uh spec remove <jogador>{ci}: Remove um espectador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:175 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "{cc}/uh spec list{ci}: Lista dos espectadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:183 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "" +"{cc}/uh spec {ci}: Edita os espectadores. Digite /uh spec para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "{cs}A partir de agora você está falando apenas com a sua equipe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "{cs}A partir de agora você pode falar com todos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "{cs}Você está falando com a equipe {0}{cs}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed " +"...>{ci}." +msgstr "" +"{ci}Legenda: {cc}/uh command <necessário> [opcional=valor padrão] <espaços " +"são válidos ...>{ci}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "{ce}Você não está autorizado a executar este comando." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +#, fuzzy +msgid "" +"{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "" +"{ce}Você está fora das novas dimensões do círculo {0} que agora é a área do " +"jogo." +msgstr[1] "" +"{ce}Você está fora das novas dimensões do círculo {0} que agora é a área do " +"jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "{ce}Você está fora das novas dimensões de {0}*{0} da área de jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "" +"{ci}Por favor mova-se {0} bloco para estar dentro das novas dimensões." +msgstr[1] "" +"{ci}Por favor mova-se {0} blocos para estar dentro das novas dimensões." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:325 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "" +"{ce}Impossível iniciar o jogo: pontos de teletransporte insuficientes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:326 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:399 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "{lightpurple}Teletransporte em progresso... Por favor aguarde." + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:414 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:434 +msgid "{gray}Player {0}{gray} teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:486 +msgid "{cs}All teams are teleported." +msgstr "{cs}Todas as equipes foram teletransportadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:487 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "{gray}Digite {cc}/uh start{gray} para iniciar a partida." + +#. Displayed in the action bar when the slow teleportation is finished but the +#. game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:525 +msgid "{ce}Please execute {cc}/uh start slow{ce} before." +msgstr "{ce}Digite {cc}/uh start slow{ce} antes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:531 +msgid "{ce}Please wait while the players are teleported." +msgstr "{ce}Por favor aguarde até os jogadores serem teletransportados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:631 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "" + +#. The "and" in the winners players list (like "player1, player2 and +#. player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1083 +msgctxt "winners_list" +msgid "and" +msgstr "e" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1095 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Parabéns à (equipe {1}{green}) {0} pela sua" +" vitória! {darkgreen}{obfuscated}--" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1099 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Parabéns {0} pela sua vitória! " +"{darkgreen}{obfuscated}--" + +#. The main title of the /title displayed when a team wins the game. {0} +#. becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in +#. solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1118 +msgid "{darkgreen}{0}" +msgstr "" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes +#. the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1113 +msgid "{green}This team wins the game!" +msgstr "" + +#. The subtitle of the /title displayed when a player wins the game (in solo). +#. {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1120 +msgid "{green}wins the game!" +msgstr "" diff --git a/src/main/resources/i18n/pt_BR.yml b/src/main/resources/i18n/pt_BR.yml deleted file mode 100644 index 6acd183..0000000 --- a/src/main/resources/i18n/pt_BR.yml +++ /dev/null @@ -1,506 +0,0 @@ -author: "eraizel" -keys: - load: - spawnPointAdded: "Local de spawn {0},{1} adicionado a partir das configurações" - invalidSpawnPoint: "Local de spawn inválido nas configurações: {0}" - teamAdded: "Equipe {0} adicionada a partir das configurações" - namedTeamAdded: "Equipe {0} ({1}) adicionada a partir das configurações" - invalidTeam: "Equipe inválida nas configurações: {0}" - recipeApple: "Adicionada nova receita para maçã dourada." - recipeCompass: "Adicionada nova receita para bússola." - recipeMelon: "Adicionada nova receita para melancia reluzente." - loaded: "Plugin Ultra Difícil Carregado." - - WBNotInstalled1: "{darkred}[UHC] {ce}WorldBorder não está instalado: muralhas não serão verificadas!" - WBNotInstalled2: "{gray}Também, sem WorldBorder, as muralhas não poderão ser reduzidas durante a partida (avisos excluidos)." - WBNotInstalled3: "{gray}Instale somente o plugin; o UHPlugin automaticamente o configurará." - - SPNotInstalled1: "{darkred}[UHC] {ce}SpectatorPlus não está instalado." - SPNotInstalled2: "{gray}Se desejar ter o modo de espectador, instale o Plugin; o UHPlugin automaticamente o configurará." - - PLNotInstalled1: "{darkred}[UHC] {ce}ProtocolLib é obrigatório, porém, não está instalado!" - PLNotInstalled2: "{gray}As seguintes opções requerem a presença do ProtocolLib:" - PLNotInstalledItem: "{darkgray} - {gray}{0}" - PLNotInstalled3: "{gray}ProtocolLib está disponivel aqui: {0}" - - cmd: - errorLoad: "{ce}Ocorreu um Erro, verifique o console para maiores detalhes. Isto provavelmente é um Bug." - errorUnknown: "{ce}Comando não existente. Digite /uh para ver uma lista dos comandos disponíveis." - errorUnauthorized: "{ce}Você não está autorizado a executar este comando." - - titleHelp: "{yellow}{0} - versão {1}" - legendHelp: "{ci}Legenda: {cc}/uh command <necessário> [opcional=valor padrão] <espaços são válidos ...>{ci}." - helpNextPage: "{gray}Próxima Página: /uh {0}" - - titleGameCmd: "{aqua}------ Comandos do jogo ------" - helpStart: "{cc}/uh start {ci}: Inicia o jogo." - helpStartSlow: "{cc}/uh start slow {ci}: Inicia o jogo no modo lento, em 2 etapas, para servidores pequenos." - helpShift: "{cc}/uh shift {ci}: Passa para o próximo episódio." - helpTeam: "{cc}/uh team {ci}: Edita as equipes. Digite /uh team para detalhes." - helpSpawns: "{cc}/uh spawns {ci}: Gera os locais de spawn. Digite /uh spawns para detalhes." - helpSpec: "{cc}/uh spec {ci}: Edita os espectadores. Digite /uh spec para detalhes." - helpWall: "{cc}/uh generatewalls {ci}: Gera as muralhas, de acordo com as configurações." - helpBorder: "{cc}/uh border {ci}: Edita a área do jogo. Digite /uh border para detalhes." - - titleBugCmd: "{aqua}------ Comandos para Bugs ------" - helpHeal: "{cc}/uh heal <jogador> [meios-corações=20|±diferença] {ci}: Regenera vida de um jogador para os meios-corações indicados (padrão 20)." - helpHealall: "{cc}/uh healall [meios-corações=20|±diferença] {ci}: Regenera todos os jogadores." - helpFeed: "{cc}/uh feed <jogador> [fome=20] [saturação=max] {ci}: Alimenta um jogador." - helpFeedall: "{cc}/uh feedall [fome=20] [saturação=max] {ci}: Alimenta todos os jogadores." - helpKill: "{cc}/uh kill <player> {ci}: Assinala o jogador como morto, mesmo que ele esteja desconecato." - helpResurrect: "{cc}/uh resurrect <jogador> {ci}: Ressuscita o jogador." - helpTpback: "{cc}/uh tpback <jogador> [force] {ci}: Teletransporta em segurança um jogador para o local da sua morte. Quando especificado - force - teletransporta o jogador mesmo que não seja seguro." - - titleMiscCmd: "{aqua}------ Outros Comandos ------" - helpFreeze: "{cc}/uh freeze {ci}: (Des)congela o jogo todo, ou um jogador. Digite: /uh freeze para detalhes." - helpFinish: "{cc}/uh finish {ci}: Exibe o nome do(s) vencedor(es) e lança foguetes." - helpTP: "{cc}/uh tp {ci}: Teletransporta os espectadores ou uma equipe inteira. Digite /uh tp para detalhes." - helpTimers: "{cc}/uh timers {ci}: Configura os tempos. Digite /uh timers para detalhes." - helpInfos: "{cc}/uh infos {ci}: Printa somente as informações sobre o jogo atual." - helpAbout: "{cc}/uh about {ci}: Informação sobre o Plugin e as traduções." - - teamHelpTitle: "{aqua}------ Comandos para equipes ------" - teamHelpAdd: "{cc}/uh team add <cor> {ci}: Adiciona uma equipe com uma determinada cor." - teamHelpAddName: "{cc}/uh team add <cor> <nome ...> {ci}: Adiciona uma equipe com um determinado nome e cor. Podem ser usados espaços." - teamHelpRemove: "{cc}/uh team remove <nome ...> {ci}: Remove uma equipe" - teamHelpJoin: "{cc}/uh team join <jogador> <equipe ...>{ci}: Adiciona um jogador a uma equipe. O nome da equipe pode ser a cor ou o seu determinado nome." - teamHelpLeave: "{cc}/uh team leave <jogador> {ci}: Retira um jogador da sua equipe." - teamHelpList: "{cc}/uh team list {ci}: Lista das equipes e seus jogadores." - teamHelpReset: "{cc}/uh team reset {ci}: Elimina todas as equipes." - teamHelpJoinCmd: "{cc}/join [player] <team ...> {ci}: Adiciona “jogador” (ou ele mesmo) para a equipe determinada. Sem argumentos, apresenta opção escolher equipe via chat (clicando na equipe)." - teamHelpLeaveCmd: "{cc}/leave [player] {ci}: Remove o “jogador” (ou ele mesmo) de seu time." - - spawnsHelpTitle: "{aqua}------ Comandos para os Spawns ------" - spawnsHelpAdd: "{cc}/uh spawns add {ci}: Adiciona um local de spawn para uma equipe ou jogador, no local onde é executado." - spawnsHelpAddXZ: "{cc}/uh spawns add <x> <z> {ci}: Adiciona um local de spawn para uma equipe ou jogador, nas coordenadas inseridas, no mundo padrão." - spawnsHelpGenerate: "{cc}/uh spawns generate {ci}: Automaticamente gera locais de spawn. Digite: /uh spawns generate para mais detalhes." - spawnsHelpGenerateDetailsCmdTitle: "{aqua}Comandos" - spawnsHelpGenerateDetailsCmd: "{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] [xCenter] [zCenter] [world]" - spawnsHelpGenerateDetailsShapesTitle: "{aqua}Formatos" - spawnsHelpGenerateDetailsShapesRandom: " - {cc}random{ci}: Gera locais de spawn randomicos no mapa, com uma distância mínima entre eles." - spawnsHelpGenerateDetailsShapesGrid: " - {cc}grid{ci}: Gera locais de spawn em forma de quadrados concêntricos, com uma distância constante entre dois pontos gerados." - spawnsHelpGenerateDetailsShapesCircular: " - {cc}circular{ci}: Gera locais de spawn em forma de círculos concêntricos, com uma distância constante entre dois pontos gerados. Em cada círculo, o ângulo (e a distância) entre dois locais de spawn é constante." - spawnsHelpGenerateDetailsArgsTitle: "{aqua}Argumentos" - spawnsHelpGenerateDetailsArgsSize: " - {cc}size{ci}: É o tamanho da região onde os locais de spawn serão gerados. Quadrado ou circular, seguindo o formato do mapa. O padrão é o tamanho do mapa." - spawnsHelpGenerateDetailsArgsDistanceMin: " - {cc}distanceMin{ci}: É a distância mínima entre dois locais de spawn. Padrão: 250 blocos." - spawnsHelpGenerateDetailsArgsCount: " - {cc}count{ci}: É o número de locais de spawn a serem gerados. Padrão: o número de jogadores ou de equipes." - spawnsHelpGenerateDetailsArgsCenter: " - {cc}xCenter{ci}, {cc}zCenter{ci}: O centro da região onde os pontos são gerados. Padrão: o local de spawn do mundo." - spawnsHelpGenerateDetailsArgsWorld: " - {cc}world{ci}: O mundo onde os locais de spawn serão gerados." - spawnsHelpList: "{cc}/uh spawns list {ci}: Lista dos locais de spawn registrados." - spawnsHelpDump: "{cc}/uh spawns dump {ci}: Mostra os locais de spawn em um formato exportável. {gray}Podendo ser utilizados em alguns sites para ver os locais de spawn por exemplo." - spawnsHelpRemove: "{cc}/uh spawns remove [<x> <z>] {ci}: Remove coordenadas de spawn inseridas, ou o local onde o comando é executado se não forem inseridas coordenadas." - spawnsHelpReset: "{cc}/uh spawns reset {ci}: Remove todos os locais de spawn registrados." - - specHelpTitle: "{aqua}------ Comandos iniciais para Espectadores ------" - specHelpNoticeSpectatorPlusNotInstalled: "{ce}ATENÇÃO{ci}: Como o Plugin SpectatorPlus não está instalado, um espectador é {italic}apenas{ci} um jogador ignorado." - specHelpAdd: "{cc}/uh spec add <jogador>{ci}: Adiciona um espectador." - specHelpRemove: "{cc}/uh spec remove <jogador>{ci}: Remove um espectador." - specHelpList: "{cc}/uh spec list{ci}: Lista dos espectadores." - - freezeHelpTitle: "{aqua}------ Comandos para Congelar ------" - freezeHelpOn: "{cc}/uh freeze on [jogador]{ci}: Congela um jogador, ou a si mesmo se o jogador não for especificado." - freezeHelpOff: "{cc}/uh freeze off [jogador]{ci}: Descongela um jogador, ou a si próprio, mesmo com todo o jogo congelado." - freezeHelpAll: "{cc}/uh freeze all{ci}: Congela o jogo todo (jogadores, mobs, tempo)." - freezeHelpNone: "{cc}/uh freeze none{ci}: Descongela o jogo todo. Você DEVE executar este comando para que o tempo do jogo volte a contar." - - borderHelpTitle: "{aqua}------ Comandos para área do jogo ------" - borderHelpCurrent: "{cc}/uh border current{ci}: Informa o tamanho atual do mapa." - borderHelpSet: "{cc}/uh border set <tamanho> [force]{ci}: Muda o tamanho do mapa. Se o comando force não for indicado, a operação será cancelada se houver algum jogador fora da nova área." - borderHelpWarning: "{cc}/uh border warning <tamanhofuturo> [minutos para a redução]{ci}: Informa todos os jogadores que estão fora da futura área. É apenas um AVISO, nada acontece." - borderHelpWarningCancel: "{cc}/uh border warning cancel{ci}: Cancela os avisos da mudança na área de jogo." - borderHelpCheck: "{cc}/uh border check <tamanho>{ci}: Retorna uma lista dos jogadores que se encontram fora da área especificada." - - tpHelpTitle: "{aqua}------ Comandos para Teletransporte ------" - tpHelpTeam: "{cc}/uh tp team <x> <y> <z> | <objetivo> <equipe ...> {ci}: Teletransporta uma equipe toda para um determinado local/objetivo." - tpHelpSpectators: "{cc}/uh tp spectators <x> <y> <z> | <objetivo> {ci}: Teletransporta os espectadores (ou seja, os jogadores mortos) para um determinado local/objetivo." - - timersHelpTitle: "{aqua}------ Comandos para a contagem de Tempo ------" - timersHelpAdd: "{cc}/uh timers add <duração> <título ...> {ci}: Adiciona um cronômetro." - timersHelpSet: "{cc}/uh timers set <duração> <título ...> {ci}: Configura a duração de um cronômetro." - timersHelpDisplay: "{cc}/uh timers display <título ...> {ci}: Mostra um cronômetro no placar. Automático quando um cronômetro e iniciado." - timersHelpHide: "{cc}/uh timers hide <título ...> {ci}: Esconde um cronômetro do placar. Não para o cronômetro." - timersHelpStart: "{cc}/uh timers start <título ...> {ci}: Inicia um cronômetro." - timersHelpPause: "{cc}/uh timers pause <título ...> {ci}: Pausa um cronômetro." - timersHelpResume: "{cc}/uh timers resume <título ...> {ci}: Reinicia o cronômetro parado com o comando pause." - timersHelpStop: "{cc}/uh timers stop <título ...> {ci}: Para um cronômetro. O cronômetro é removido do placar." - timersHelpRemove: "{cc}/uh timers remove <título ...> {ci}: Remove um cronômetro." - timersHelpList: "{cc}/uh timers list {ci}: Lista de todos os cronômetros registrados." - timersHelpDurations: "{gray}'<duração>' formato : mm, mm:ss ou hh:mm:ss." - - about: - authors: "Plugin feito com amor por {0}." - and: "e" - - build: - number: "Versão Número: {0}." - notAvailable: "O número da versão não está disponível." - - i18n: - title: "{aqua}------ Traduções ------" - selected: "Linguagem Selecionada: {0} (traduzido por {1})." - fallback: "Linguagem Secundária: {0} (traduzido por {1})." - license: - title: "{aqua}------ Licença ------" - license: "Publicado sobre a GNU General Public License (versão 3)." - - start: - already: "{ce}O jogo já comecou! Recarregue ou Reinicie o servidor para reiniciar o jogo." - syntax: "{ce}Erro de sintaxe. Digite: /uh start [slow] ou /uh start slow go." - notEnoughTP: "{ce}Impossível iniciar o jogo: pontos de teletransporte insuficientes." - teleportationInProgress: "{lightpurple}Teletransporte em progresso... Por favor aguarde." - - startSlowBeforeStartSlowGo: "{ce}Digite {cc}/uh start slow{ce} antes." - startSlowWaitBeforeGo: "{ce}Por favor aguarde até os jogadores serem teletransportados." - startSlowTeamTP: "{gray}Equipe {0}{gray} teletransportada." - startSlowAllTeamsTP: "{cs}Todas as equipes foram teletransportadas." - startSlowAllTeamsTPCmd: "{gray}Digite {cc}/uh start slow go{gray} para iniciar a partida." - - go: "{green}----- Começou! -----" - - finish: - notStarted: "{ce}A partida ainda não iniciou!" - notFinished: "{ce}Não há nenhuma equipe viva!" - - and: "e" - - broadcast: - withTeams: "{darkgreen}{obfuscated}--{green} Parabéns à (equipe {1}{green}) {0} pela sua vitória! {darkgreen}{obfuscated}--" - withoutTeams: "{darkgreen}{obfuscated}--{green} Parabéns {0} pela sua vitória! {darkgreen}{obfuscated}--" - - episodes: - end: "{aqua}-------- Fim do Episódio {0} --------" - endForced: "{aqua}-------- Fim do Episódio {0} [forcado por {1}] --------" - - scoreboard: - episode: "{gray}Episódio {white}{0}" - players: "{white}{0}{gray} Jogadores" - teams: "{white}{0}{gray} Equipes" - timer: "{white}{0}{gray}:{white}{1}" - timerWithHours: "{0}{gray}:{white}{1}{gray}:{white}{2}" - - motd: - beforeStart: "Aguardando jogadores..." - starting: "Iniciando a partida..." - runningSolo: "Partida em andamento! {0} jogadores vivos." - runningTeams: "Partida em andamento! {0} jogadores vivos em {1} equipes." - finishedSolo: "Partida encerrada! Parabéns ao jogador {0} pela sua vitória!" - finishedTeams: "Partida encerrada! A equipe {0} foi a vencedora!" - - death: - kickMessage: "Ha! Ha! Levou uma Butinada!" - banMessage: "Morreu :˜(" - teamHasFallen: "{0}Todos os jogadores da equipe {1} morreram!" - - canRespawn: "{darkpurple}{obfuscated}----{lightpurple}{italic} Você pode renascer{lightpurple}, clique em {italic}Renascer {lightpurple}na próxima tela." - - craft: - goldenApple: - loreLine1Player: "Feita da cabeça" - loreLine2Player: "de {0}" - loreLine1Monster: "Feita da cabeça" - loreLine2Monster: "de um monstro malígno" - - nameGoldenAppleFromHeadNormal: "{aqua}Maçã Dourada" - nameGoldenAppleFromHeadNotch: "{lightpurple}Maçã Dourada" - - compass: - noRottenFlesh: "{gray}{italic}Para a bússola é necessária carne podre." - nothingFound: "{gray}{italic}Nenhum jogador encontrado nas proximidades." - success: "{gray}A bússola está apotando para o jogador mais próximo de você." - - dynmap: - markerLabelDeath: "local onde {0} morreu" - markerLabelSpawn: "Local de spawn da equipe {0}" - markerLabelSpawnNoTeam: "Local de spawn de {0}" - - wall: - startGen: "{cst}Gerando as muralhas..." - consoleDefaultWorld: "{ci}A partir do console, gerando a área para o mundo padrão, {0}" - error: "{ce}Impossível gerar a área: verifique os logs para detalhes. Os blocos configurados são provavelmente inválidos." - unknownError: "{ce}Ocorreu um erro, verifique o console para maiores detalhes." - blocksError: "Impossível construir as muralhas, os blocos nas configurações são inválidos." - done: "{cst}Muralhas criadas com sucesso." - - spawns: - NaN: "{ce}Este não e um número!" - syntaxError: "{ce}Erro de sintaxe; Digite: /uh spawns." - errorCoords: "{ce}As coordenadas precisam ser inseridas a partir do console." - error2Coords: "{ce}É necessária a especificação de pelo menos duas coordenadas." - - add: - added: "{cs}Local de spawn adicionado ao mundo {0}: {1};{2}" - outOfLimits: "{ce}Locais de spawn só são possíveis dentro das muralhas." - noSafeSpot: "{ce}Impossível adicionar este local de spawn: não foi encontrado um local seguro no Inferno." - - assumptions: - solo: "{ci}Nenhuma equipe encontrada. Assumirei que o jogo está em modo solo." - partialSolo: "{ci}Alguns jogadores não estão em nenhuma equipe; este número foi adicionado ao número de locais de spawn." - - generate: - nothingToDo: "{ci}Você especificou uma geração nula. Portanto, a geração está vazia." - unsupportedMethod: "{ce}O método de geração “{0}” (ainda?) não foi implementado." - unknownWorld: "{ce}O mundo {0} não existe." - success: "{cs}Os Locais de spawn especificados foram gerados com sucesso." - impossible: "{ce}A sua especificação é impossível: existem muitos locais de spawn em um espaço limitado. Corrija este erro reduzindo o número de locais spawn ou o espaço mínimo entre dois pontos." - - list: - nothing: "{ce}Não existe nenhum local de spawn registrado." - count: "{ci}Existem {0} locais de spawn registrados." - world: "{lightpurple}Mundo {0}" - item: - overworld: "{green}{0}{darkgreen};{green}{1}" - nether: "{red}{0}{darkred};{red}{1}" - end: "{yellow}{0}{gold};{yellow}{1}" - other: "{gray}{0}{darkgray};{gray}{1}" - - remove: - removed: "{cs}O local de spawn {1};{2} no mundo {0} foi removido." - - reset: "{cs}Todos os locais de spawn foram removidos." - - team: - syntaxError: "{ce}Erro de sintaxe. Digite: /uh team para ver os comandos disponíveis." - unknownCommand: "{ce}Comando desconhecido. Digite /uh team para ver os comandos disponíveis." - onlyAsAPlayer: "{ce}Este comando só pode ser executado dessa forma se você for um jogador." - - add: - errorColor: "{ce}Impossível criar a equipe, verifique a cor. Dica: use Tab para auto completar." - errorExists: "{ce}Esta equipe já existe." - added: "{cs}Equipe {0}{cs} adicionada." - - remove: - doesNotExists: "{ce}Equipe inexistente." - removed: "{cs}Equipe {0} removida." - - addplayer: - disconnected: "{ce}Impossível adicionar {0} à equipe {1}." - success: "{cs}O jogador {0} foi adicionado com sucesso à equipe {1}" - added: "{aqua}Você foi adicionado à equipe {0}{aqua}." - doesNotExists: "{ce}Esta equipe não existe." - full: "{ce}A equipe {0}{ce} já está lotada!" - - joinhelp: "{ce}Digite: {cc}/join [jogador] <equipe>{ce}." - - removeplayer: - disconnected: "{ce}O jogador {0} está desconectado!" - success: "{cs}O jogador {0} foi removido com sucesso de sua equipe." - removed: "{darkaqua}Você não faz mais parte da equipe {0}{darkaqua}." - - list: - nothing: "{ce}Não há nenhuma equipe para ser mostrada." - - itemTeam: "{0} ({1} jogadores)" - - bulletPlayerOnline: "{green} • " - bulletPlayerOffline: "{red} • " - - itemPlayer: "{0}" - - gui: - choose: "{gold}Clique em um nome abaixo para se juntar a esta equipe" - playersCount: "{gray}[{white}{0}{gray}/{white}{1}{gray}]" - playersCountUnlimited: "{gray}[{white}{0}{gray}]" - tooltipCount: "{0} jogador(es) nesta equipe" - tooltipJoin: "Clique aqui para juntar-se à equipe {0}" - tooltipJoinInside: "Você agora faz parte da equipe {0}" - leaveTeam: "{darkred}[\u00D7] {red}Clique aqui para deixar esta equipe" - howToDisplayAgain: "{gray}Digite: /join para ver estas opções novamente" - noTeams: "{ce}Não há nenhuma equipe disponível." - - reset: - success: "{cs}Todas as equipes foram removidas." - - message: - noConsole: "{ce}Não é possível enviar mensagens de equipe a partir do console." - noTeam: "{ce}Você não pertence a nenhuma equipe!" - usage: "{ce}Digite: /{0} <mensagem>" - - notAllowed: - self: "{ce}Não lhe é permitido enviar mensagens privadas para a sua equipe." - others: "{ce}Não lhe é permitido entrar no chat privado de outra equipe." - - toggle: - nowTeamChat: "{cs}A partir de agora você está falando apenas com a sua equipe." - nowGlobalChat: "{cs}A partir de agora você pode falar com todos." - - nowOtherTeamChat: "{cs}Você está falando com a equipe {0}{cs}." - unknownTeam: "{ce}Equipe inexistente." - - format: "{gold}[{0}{gold} -> equipe dele] {reset}{1}" - formatOtherTeam: "{gold}[{0}{gold} -> equipe {1}{gold}] {reset}{2}" - - infos: - notStarted: "{ci}A partida não começou." - players: "{ci}{0} jogadores vivos em {1} equipes." - - bulletOnline: "{green} • " - bulletOffline: "{red} • " - - separatorAliveState: "{gray} - " - - dead: "{red}morto" - alive: "{green}vivo" - - tooltips: - online: "Online neste momento" - offline: "Offline neste momento" - - team: "Equipe: {0}" - - health: "{0} meios-corações" - - shift: - consoleName: "O console" - cantNotStarted: "{ce}Não é possível passar para o próximo episódio porque o jogo ainda não começou." - - heal: - usage: "{ce}Digite: /uh heal <jogador> [número de meios-corações = 20]" - offline: "{ce}Este jogador está desconectado." - errorNaN: "{ce}Insira um número de meios-corações não um texto." - errorNoKill: "{ce}Não é permitido matar jogadores com este comando, isto pode causar falhas na escrita." - errorHealthNotUpdatedNoKill: "{ce}A vida de {0} não foi atualizada pois isso causaria a sua morte." - allErrorNoKill: "{ce}Assassino!" - - feed: - usage: "{ce}Digite: /uh feed <jogador> [Pontos de alimentação = 20] [saturação = max]" - offline: "{ce}Este jogador está desconectado." - errorNaN: "{ce}Pontos de alimentacão e saturacão precisam ser números (a saturacão em fração, por exemplo: 2.2)!" - - kill: - usage: "{ce}Digite: /uh kill <jogador>" - neverPlayed: "{ce}Este jogador não existe no servidor." - notAlive: "{ce}{0} não é um jogador vivo." - killed: "{cs}O jogador {0} agora está morto." - - resurrect: - usage: "{ce}Digite: /uh resurrect <jogador>" - unknownOrDead: "{ce}Este jogador não está jogando ou já se encontra morto!" - offlineOk: "{cs}Porque {0} está desconectado, quando ele ficar online será resuscitado. Se estava banido, ja não está." - notDead: "{ce}{0} não está morto!" - broadcastMessage: "{gold}{0} foi ressuscitado!" - - tpback: - usage: "{ce}Digite: /uh tpback <jogador> [force]" - offline: "{ce}O jogador {0} não está online." - noDeathLocation: "{ce}O jogador {0} não possui um local de morte." - teleported: "{cs}O jogador {0} foi teletransportado para o local da sua morte." - notTeleportedNoSafeSpot: "{ce}O jogador {0} não foi teletransportado porque não foi encontrado um local seguro para esta operação." - notTeleportedNoSafeSpotCmd: "{ci}Digite: {cc}/uh tpback {0} force{ci} para teletransportar o jogador mesmo que o local não seja seguro." - - tp: - NaN: "{ce}As coordenadas precisam conter três números válidos." - targetOffline: "{ce}{0} não está online!" - teamDoesNotExists: "{ce}Esta equipe não está registrada." - - spectators: - syntaxError: "{ce}Erro de sintaxe. Digite: /uh spec para detalhes." - unknownCommand: "{ce}Comando Desconhecido. Digite: /uh spec para ver uma lista de comandos disponíveis." - offline: "{ce}{0} não está online." - - add: - success: "{cs}O jogador {0} está agora em modo espectador." - - remove: - success: "{cs}Modo espectador desativado para {0}, agora ele e um jogador." - - list: - nothing: "{ce}Não há nenhum espectador para ser listado." - countSpectators: "{ci}{0} Espectador(es) registrado(s)." - countOnlyInitial: "{ci}Este número inclui apenas os espectadores iniciais." - itemSpec: "{lightpurple} - {0}" - - freeze: - frozen: "{cst}Você foi congelado por {0}." - unfrozen: "{cst}Você foi descongelado por {0}." - - playerFrozen: "{cs}{0} está agora congelado." - playerUnfrozen: "{cs}{0} está agora descongelado." - - playerOnly: "{ce}Você precisa estar jogando para executar este comando desta maneira." - offline: "{ce}{0} não está online!" - - scoreboard: "{darkaqua}O jogo está congelado" - - broadcast: - globalFreeze: "{darkaqua}O jogo inteiro está congelado." - globalUnfreeze: "{darkaqua}O jogo continua." - - borders: - syntaxError: "{ce}Erro de sintaxe. Digite: /uh border para detalhes." - NaN: "{ce}“{0}” não e um número..." - - current: - messageSquared: "{ci}A área atual do mapa quadrado é {0}*{0}." - messageCircular: "{ci}A área atual do mapa circular e de {0} blocos." - - set: - playersOutsideCanceled: "{ce}Alguns jogadores estão fora da nova área. A operação foi cancelada." - playersOutsideCanceledCmd: "{ci}Digite: {cc}/uh border set {0} force{ci} para estabelecer uma nova dimensão, mesmo que haja jogadores fora da área." - playersOutsideCanceledWarnWorldBorder: "{ce}ATENÇÃO: {ci}O Plugin WorldBorder não está instalado, jogadores que estejam fora da área não serão teletransportados!" - - broadcastSquared: "{lightpurple}A área atual do mapa quadrado é {0}*{0}." - broadcastCircular: "{lightpurple}A área atual do mapa circular e de {0} blocos." - - warning: - canceled: "{cs}Alertas cancelados." - - set: "{cs}Novas dimensões salvas. Todos os jogadores que estejam fora das novas dimensões serão avisados a cada {0} segundos." - - messageSquared: "{ce}Você está fora das novas dimensões de {0}*{0} da área de jogo." - messageCircular: "{ce}Você está fora das novas dimensões do círculo {0} que agora é a área do jogo." - - messageDistance: "{ci}Por favor mova-se {0} blocos para estar dentro das novas dimensões." - messageDistanceTime: "{ci}Ainda faltam {0} blocos para você estar dentro da área, e {1} minutos para que o seu tempo se esgote." - - nameTimer: "Diminuindo a área" - - timerUp: "{cs}Acabou o tempo para as novas dimensões!" - - check: - allPlayersInside: "{cs}Todos os jogadores estão dentro das novas dimensões." - countPlayersOutside: "{ci}Existem {0} jogadores fora das novas dimensões." - - itemPlayerFar: "{lightpurple} - {red}{0}{ci} (Longe dos novas dimensões)" - itemPlayerClose: "{lightpurple} - {yellow}{0}{ci} (Perto dos novas dimensões)" - itemPlayerVeryClose: "{lightpurple} - {green}{0}{ci} (Muito Perto dos novas dimensões)" - - timers: - syntaxError: "{ce}Erro de sintaxe. Digite: /uh timers para detalhes." - durationSyntaxError: "{ce}A duração inserida é inválida. Os formatos aceitáveis são mm ou mm:ss ou hh:mm:ss." - timerDoesNotExists: "{ce}Este cronômetro é inexistente." - alreadyExists: "{ce}Um cronômetro com o nome {0}{ce} já existe; Por favor, renomeie o seu cronômetro." - - added: "{cs}O cronômetro {0}{cs} (com duração {1}) foi adicionado." - set: "{cs}A duração do cronômetro {0}{cs} é agora de {1}." - displayed: "{cs}O cronômetro {0}{cs} está sendo exibido." - hidden: "{cs}O cronômetro {0}{cs} está ocultado." - started: "{cs}O cronômetro {0}{cs} foi iniciado." - paused: "{cs}O cronômetro {0}{cs} foi parado." - resumed: "{cs}O cronômetro {0}{cs} foi retomado." - stopped: "{cs}O cronômetro {0}{cs} foi interrompido." - removed: "{cs}O cronômetro {0}{cs} foi removido." - - list: - count: "{ci}Ao todo foram registrados {0} cronômetroes." - itemRunning: "{green} • {ci}{0}{ci} - total de {1} segundos - {2}" - itemPaused: "{yellow} • {ci}{0}{ci} - total de {1} segundos - {2}" - itemStopped: "{red} • {ci}{0}{ci} - total de {1} segundos" - - protips: - base: "{darkpurple}Dica!" - - teamchat: - lock: "{gray}Você pode digitar {cc}/togglechat{gray} para mudar e bloquear o chat entre o chat de equipe e o chat global." - useTCommand: "{gray}Para enviar mensagens rápidas para a sua equipe digite: {cc}/t <mensagem>{gray}." - useGCommand: "{gray}Para enviar mensagens rápidas para todos digite: {cc}/g <mensagem>{gray}." - - crafts: - goldenHead: "{gray}Você pode fazer maçãs douradas com cabeças (da mesma maneira que você faria com uma maçã use a cabeça)." - compassEasy: "{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, um olho de aranha e uma pólvora." - compassMedium: "{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, um olho de aranha e uma pólvora; no centro, uma enderpearl." - compassHard: "{gray}Para fazer uma bússola coloque, nos cantos, um osso, uma carne podre, um olho de aranha e uma pólvora; no centro, um olho de ender." - glisteringMelon: "{gray}A melancia reluzente e feita com uma melancia e um bloco de ouro." - noEnchGoldenApple: "{gray}As maçãs douradas encantadas (ou do capiroto) estão desativadas para este jogo." - - start: - invincibility: "{gray}Caiu em uma árvore? Pule, você ainda têm 25 segundos de invencibilidade." diff --git a/src/main/resources/i18n/pt_PT.po b/src/main/resources/i18n/pt_PT.po new file mode 100644 index 0000000..699ef0e --- /dev/null +++ b/src/main/resources/i18n/pt_PT.po @@ -0,0 +1,2299 @@ +# Copyright or © or Copr. João Roda (2014 - 2016) +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: João Roda\n" +"POT-Creation-Date: 2016-01-20 03:37+0100\n" +"PO-Revision-Date: 2016-01-20 14:19:49.623502\n" +"Last-Translator: João Roda\n" +"Language-Team: João Roda\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. The name of the warning timer displaying the time left before the next +#. border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:84 +msgid "Border shrinking" +msgstr "Proximos Limites" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:363 +msgid "{cs}All players are inside the given border." +msgstr "{cs}Todos os Jogadores estao dentro dos Novos Limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:367 +msgid "{ci}There are {0} players outside the given border." +msgstr "{ci}Estao {0} jogadores fora dos Novos Limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:373 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "{lightpurple} - {red}{0}{ci} (Longe dos Novos Limites)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:377 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "{lightpurple} - {yellow}{0}{ci} (Perto dos Novos Limites)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:381 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "{lightpurple} - {green}{0}{ci} (Muito Perto dos Novos Limites)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{red}Warning!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{white}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:425 +msgid "{red}{bold}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:426 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "" +"{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "" +"{gray}Podes usar {cc}/togglechat{gray} para mudar e bloquear o chat entre o " +"chat de Equipa e o chat Global." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "" +"{gray}Para enviares mensagens rapidas para todos usa {cc}/g " +"<mensagem>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "" +"{gray}Para enviares mensagens rapidas para a tua equipa usa {cc}/t " +"<mensagem>{gray}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "" +"{gray}Podes fazer Macas Douradas com cabecas (a mesma maneira mas com uma " +"cabeca em vez de uma maca)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder." +msgstr "" +"{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho " +"de aranha e uma polvora." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an ender pearl." +msgstr "" +"{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho " +"de aranha e uma polvora; no centro, uma enderpearl." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "" +"{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho " +"de aranha e uma polvora; no centro, um olho do fim." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "" +"{gray}A melancia reluzente e feita com uma melancia e um bloco de ouro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "{gray}As Macas Douradas Encantadas estao desativadas para este jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "" +"{gray}Caiste numa Arvore? Salta, ainda tens 25 segundos de invencibilidade." + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:131 +msgid "{darkpurple}ProTip!" +msgstr "{darkpurple}Dica!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:204 +msgid "Ultra Hardcore plugin loaded." +msgstr "Ultra Hardcore plugin Carregado." + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:61 +msgid "{0} » {darkred}Delete" +msgstr "" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:69 +msgid "{green}Keep this team alive" +msgstr "" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:81 +msgid "{red}Delete this team {italic}forever" +msgstr "" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:68 +msgid "{0} » {black}Members" +msgstr "" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:77 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:123 +msgid "{green}« Go back" +msgstr "" + +#. The title of a button to select a player (a skull button). {0} = player's +#. display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:67 +msgid "Teams » {black}{0}" +msgstr "" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:73 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "" +msgstr[1] "" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{green}Update the color" +msgstr "" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:83 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:90 +msgid "{green}Rename the team" +msgstr "" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:92 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "{green} • " + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "{red} • " + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:106 +msgid "{green}Add or remove players" +msgstr "" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{red}Delete this team" +msgstr "" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:116 +msgid "{gray}Cannot be undone" +msgstr "" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:77 +msgid "{black}Select a team {reset}({0})" +msgstr "" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{white}Rename your team" +msgstr "" + +#. Warning displayed in the "Rename your team" button, if the player is not in +#. a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:91 +msgid "{gray}You have to be in a team" +msgstr "" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:100 +msgid "{white}New team" +msgstr "" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:118 +msgid "{blue}Players" +msgstr "" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "" + +#. Title of the team item in the teams selector GUI (with max). {0}: team +#. display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:177 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "" + +#. Title of the team item in the teams selector GUI (without max) {0}: team +#. display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:179 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "" +msgstr[1] "" + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "" + +#. The title of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "" + +#. The legend of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "" + +#. The summary title in the final « create the team » button of the create +#. team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "" + +#. The team name in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "" + +#. The team color in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "" + +#. The team members count in the final « create the team » button of the +#. create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:173 +msgid "{cs}Team created." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:177 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:118 +msgid "{ce}This team already exists." +msgstr "{ce}Esta Equipa ja existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:208 +#, java-format +msgid "Spawn point {0},{1} added from the config file" +msgstr "Ponto de Spawn {0},{1} adicionado a partir das configuracoes" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:213 +#, java-format +msgid "Invalid spawn point set in config: {0}" +msgstr "Ponto de Spawn invalido nas configuracoes: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:141 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:302 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "{aqua}Estas agora na {aqua}Equipa {reset}{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:335 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:369 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "{darkaqua}Tu ja nao fazes parte da Equipa {0}{darkaqua}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:84 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:211 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "{ce}Nao te e permitido enviar mensagens privadas para a tua Equipa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:216 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "{ce}Nao te e permitido entrar no chat privado de outra equipa." + +#. Format of a private team message from a team member. {0} = sender display +#. name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:99 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "{gold}[{0}{gold} -> Equipa] {reset}{1}" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:105 +msgid "{ce}You are not in a team!" +msgstr "{ce}Nao estas em nenhuma Equipa!" + +#. Format of a private team message from a non-team-member. {0} = sender +#. display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:112 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "{gold}[{0}{gold} -> Equipa {1}{gold}] {reset}{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:443 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:461 +#, java-format +msgid "Invalid team set in config: {0}" +msgstr "Equipa invalida nas configuracoes: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:450 +#, java-format +msgid "Team {0} ({1}) added from the config file" +msgstr "Equipa {0} ({1}) adicionada a partir das configuracoes" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:456 +#, java-format +msgid "Team {0} added from the config file" +msgstr "Equipa {0} adicionada a partir das configuracoes" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:497 +msgid "{gold}Click on the names below to join a team" +msgstr "{gold}Clica nos nomes em baixo para juntar a uma equipa" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. +#. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:511 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "{gray}[{white}{0}{gray}/{white}{1}{gray}]" + +#. Team count without max players (ex. [3]) followed in-game by the team name. +#. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:516 +msgid "{gray}[{white}{0}{gray}]" +msgstr "{gray}[{white}{0}{gray}]" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:534 +msgid "{0} ({red}dead{reset})" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:539 +msgid "{0} ({green}alive{reset})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:544 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "{0} jogador nesta equipa" +msgstr[1] "{0} jogadores nesta equipa" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = +#. team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:557 +#, java-format +msgid "You are in the team {0}" +msgstr "Estas agora na Equipa {0}" + +#. Tooltip on the chat team selector GUI when the player is not in the team. +#. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:562 +#, java-format +msgid "Click here to join the team {0}" +msgstr "Clica aqui para juntares a equipa {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:574 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "{darkred}[×] {red}Clica aqui para saires da tua Equipa" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "{gray}Faz /join para mostrar isto outra vez." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "{ce}Nao ha nenhuma Equipa registada." + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:162 +msgid "jayjay" +msgstr "Foste MORTO!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:240 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "{0}A Equipa {1} foi extinguida!" + +#. A message displayed to the players under the death screen, about the +#. respawn possibility even if the death screen says the opposite (in hardcore +#. mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:284 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} PODES " +"RENASCER{lightpurple}, clica em {italic}Renascer {lightpurple}no proximo " +"ecra." + +#. The kick message displayed if a player tries to relog after his death and +#. it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:442 +msgid "You are dead!" +msgstr "Foste MORTO!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:515 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "" +"{darkred}[UHC] {ce}WorldBorder nao esta instalado: paredes nao serao " +"verificadas!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:516 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game" +" (warnings excluded)." +msgstr "" +"{gray}Tambem, sem WorldBorder, as paredes nao podem ser diminuidas em Jogo " +"(Avisos excluidos)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:517 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "{gray}Instala so o plugin; UHPlugin automaticamente o configura." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:527 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "{darkred}[UHC] {ce}ProtocolLib e preciso mas nao esta instalado!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:528 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "{gray}As seguintes opcoes precisam do ProtocolLib:" + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = +#. option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:532 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "{darkgray} - {gray}{0}" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:545 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "{gray}ProtocolLib esta disponivel aqui: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:673 +msgid "{cs}The timer before the new border is up!" +msgstr "{cs}Acabou o tempo para os Novos Limites!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:705 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "{aqua}-------- Fim do Episodio {0} [forcado por {1}] --------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:709 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "{aqua}-------- Fim do Episodio {0} --------" + +#. The title displayed when the episode change. {0} = new episode number; {1} +#. = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:721 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "" + +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:745 +msgid "{green}--- GO ---" +msgstr "{green}----- GO GO GO -----" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:753 +msgid "{darkgreen}Let's go!" +msgstr "" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:755 +msgid "{green}Good luck, and have fun" +msgstr "" + +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:887 +msgid "{gold}{0} returned from the dead!" +msgstr "{gold}{0} foi ressuscitado!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:200 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:279 +msgid "{aqua}Golden head" +msgstr "{aqua}Maca Dourada" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:280 +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maca Dourada" + +#. Error message if a player tries to use his pointing compass without rotten +#. flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:304 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "{gray}{italic}Precisas de Carne Podre para utilizares a Bussola." + +#. Error message if a player tries to use his pointing compass without a +#. player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:335 +msgid "{gray}{italic}Only silence answers your request." +msgstr "{gray}{italic}Nao foram encontrados jogadores por perto." + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:342 +msgid "{gray}The compass now points to the closest player." +msgstr "{gray}A Bussola aponta agora para o jogador mais proximo." + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:152 +#, java-format +msgid "Death point of {0}" +msgstr "Ponto de Morte de {0}" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:231 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "Ponto de Spawn da Equipa {0}" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation +#. ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:236 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:293 +#, java-format +msgid "Spawn point of {0}" +msgstr "Ponto de Spawn de {0}" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +msgid "Made from the fallen head of a malignant monster" +msgstr "Feita da cabeca de uma coisa Horrivel" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:290 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "Feita da cabeca de {0}" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:393 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Maca Dourada" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:399 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maca Dourada" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:426 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "{aqua}Maca Dourada" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:432 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}Maca Dourada" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:141 +msgid "{gray}Episode {white}{0}" +msgstr "{gray}Episodio {white}{0}" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:150 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:159 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "{white}{0}{gray} Jogador" +msgstr[1] "{white}{0}{gray} Jogadores" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:163 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "{white}{0}{gray} Equipa" +msgstr[1] "{white}{0}{gray} Equipas" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:205 +msgid "{bold}Your team" +msgstr "" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:278 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "" +msgstr[1] "" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:309 +msgid "{blue}{bold}Border" +msgstr "" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:317 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "" +msgstr[1] "" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:320 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "" +msgstr[1] "" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:336 +msgid "{white}{0} {1}" +msgstr "" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:341 +msgid "{gray}X: {white}{0} {1}" +msgstr "" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}Z: {white}{0} {1}" +msgstr "" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh +#. freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:384 +msgid "{darkaqua}Game frozen" +msgstr "{darkaqua}JOGO PARADO" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:121 +msgid "{red}{bold}Rules and informations" +msgstr "" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:132 +msgid "{darkgray}- {reset}{0}" +msgstr "" + +#. Episode in the player list ({episodeText} replacement). {0} = current +#. episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "Episode {0}" +msgstr "Episodio {0}" + +#. Players in the player list ({playersText} replacement). {0} = current alive +#. players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "{0} Jogador" +msgstr[1] "{0} Jogadores" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive +#. teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:121 +#, java-format +msgid "{0} teams" +msgid_plural "{0} teams" +msgstr[0] "{0} Equipa" +msgstr[1] "{0} Equipas" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:89 +msgid "Waiting for players..." +msgstr "A Espera de Jogadores..." + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:98 +msgid "Starting in progress..." +msgstr "A Comecar..." + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:113 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "Jogo a Decorrer! {0} jogador vivos." +msgstr[1] "Jogo a Decorrer! {0} jogadores vivos." + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive +#. count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:118 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "Jogo a Decorrer! {0} jogador vivos em {1} equipa." +msgstr[1] "Jogo a Decorrer! {0} jogadores vivos em {1} equipas." + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:135 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "Jogo Terminou; Parabens a {0} pela sua Vitoria!" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:140 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "Jogo Terminou; A Equipa {0} ganhou o Jogo!" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "{0}{gray}:{white}{1}{gray}:{white}{2}" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "{white}{0}{gray}:{white}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "{aqua}------ Comandos de Jogo ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "{aqua}------ Comandos para Bugs ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "{aqua}------ Outros Comandos ------" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:107 +msgid "{ce}Usage: /{0} <message>" +msgstr "{ce}Usa: /{0} <mensagem>" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "{aqua}------ Comandos para os Spawns ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "" +"{cc}/uh spawns {ci}: gere os pontos de spawn. Faz /uh spawns para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "{ce}As coordenadas tem que ser tres numeros validos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "{ce}Esta Equipa nao esta Registada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "{ce}{0} esta OFFLINE!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "{aqua}------ Comandos para Teleporte ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" +"{cc}/uh tp team <x> <y> <z> | <jogador> <equipa ...> {ci}: teleportar uma " +"equipa para um local ou jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" +"{cc}/uh tp spectators <x> <y> <z> | <jogador> {ci}: teleporta os " +"espectadores (tal como os jogadores mortos) para um local ou jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "" +"{cc}/uh tp {ci}: teleporta os Espectadores ou uma Equipa inteira. Faz /uh tp" +" para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "{yellow}{0} - versao {1}" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "e" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "Plugin feito com amor por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "Numero da Build: {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "Numero de Build nao Disponivel." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "{aqua}------ Traducoes ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "Linguagem Selecionada: {0} (traduzido por {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "Linguagem para Erros: {0} (traduzido por {1})." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "{aqua}------ Licenca ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "Publicado sobre a CeCILL-B License." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "{cc}/uh about {ci}: informacao sobre o Plugin e as Traducoes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:67 +msgid "{cs}Warning canceled." +msgstr "{cs}Avisos Cancelados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:82 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "" +"{cs}Limite Futuro Salvo. Todos os Jogadores fora dos Futuros Limites serao " +"avisados a cada {0} segundo." +msgstr[1] "" +"{cs}Limite Futuro Salvo. Todos os Jogadores fora dos Futuros Limites serao " +"avisados a cada {0} segundos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:124 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "{ce}“{0}” nao e um Numero..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" +"{cc}/uh border warning <tamanhofuturo> [minutos para a reducao]{ci}: avisa " +"todos os jogadores fora dos futuros limites. E so um AVISO, nao acontece " +"nada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "" +"{cc}/uh border warning cancel{ci}: cancela os avisos do /uh border warning." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "" +"{ce}Alguns jogadores estao fora dos Futuros Limites. A operacao foi " +"CANCELADA." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "" +"{ci}Usa {cc}/uh border set {0} force{ci} para aplicares os Futuros Limites, " +"mesmo com os jogadores Fora dos Limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "" +"{ce}AVISO: {ci}WorldBorder nao esta Instalado, Jogadores fora dos Limites " +"nao serao Teleportados!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:114 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "{lightpurple}O Tamanho do Limte Circular e agora {0} bloco." +msgstr[1] "{lightpurple}O Tamanho do Limte Circular e agora {0} blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:118 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "{lightpurple}O Tamanho dos Limites e agora {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:149 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" +"{cc}/uh border set <tamanho> [force]{ci}: muda o limite das paredes. Se nao " +"for indicado o force, a operacao sera cancelada se tiver algum jogador fora " +"dos novos limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "" +"{cc}/uh border check <tamanho>{ci}: faz uma lista dos jogadores fora dos " +"limites dados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "{ci}O Tamanho atual do Limite Circular e de {0} bloco." +msgstr[1] "{ci}O Tamanho atual do Limite Circular e de {0} blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "{ci}O Tamanho atual do Limite e {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "{cc}/uh border get{ci}: diz o tamanho dos limites atuais." + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "{ci}{0} jogador vivos em {1} team." +msgstr[1] "{ci}{0} jogadores vivos em {1} teams." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "{ci}O Jogo ainda nao comecou." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "Atualmente Online" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "Atualmente Offline " + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "Equipa: {0}" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "{gray} - " + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "{green}Vivo" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "{0} meios-coracoes" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "{red}Morto" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "" +"{cc}/uh infos {ci}: apresenta algumas infos sobre o jogo que esta a " +"decorrer." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "{ce}Fome e Saturacao tem de ser numeros!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "" +"{cc}/uh feedall [Fome=20] [Saturacao=max] {ci}: alimenta todos os jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "{cs}Ponto de Spawn adicionado no Mundo {0}: {1};{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "{ce}Nao podes adicionar um ponto de spawn fora dos Limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "" +"{ce}Impossivel adicionar este ponto de Spawn: nao foi encontrado um ponto de" +" spawn no Nether." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "{ce}Precisas de especificar pelo menos duas coordenadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "{ce}Isto nao e um numero!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "" +"{cc}/uh spawns add [<x> <z>]{ci}: adiciona um ponto de spawn para uma equipa" +" ou jogador, no local onde e executado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "{ci}Nenhuma EQUIPA encontrada. Assumindo que o jogo e em modo SOLO." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "" +"{ci}Alguns jogadores nao estao em nenhuma equipa; ficarao a jogar sozinhos; " +"foram adicionados ao numero de Pontos de Spawn necessarios." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "{ce}O Mundo {0} nao existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "" +"{ci}Pediste uma geracao nula. Portanto, nao foram gerados pontos de spawn." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "{ce}O Metodo de geração “{0}” nao e (ainda?) suportada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "" +"{ce}Pediste o Impossivel: existem demasiados pontos de spawn no espaco muito" +" pequeno. Diminui os pontos de spawn ou o espaco minimo entre dois pontos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "{cs}Pontos de Spawn gerados com sucesso." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "{aqua}Comando" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" +"{cc}/uh spawns generate <circular|grid|random> [Tamanho] [DistanciaMin] " +"[Numero de Spawns] [xCentro] [zCentro] [Mundo]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "{aqua}Formatos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr "" +" - {cc}random{ci}: gera pontos de spawns ao calhas no mapa, com uma " +"distancia minima entre eles." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr "" +" - {cc}grid{ci}: gera pontos de spawn em quadrados concentricos, com uma " +"distancia constante entre dois pontos de spawn." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" +" - {cc}circular{ci}: gera pontos de spawn em circulos concentricos, com uma " +"distancia minima entre dois pontos. Em cada circulo, o angulo (e a sua " +"distancia) entre dois pontos e constante." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "{aqua}Argumentos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr "" +" - {cc}Tamanho{ci}: o tamanho da regiao onde os pontos de spawn vao ser " +"gerados. Quadrangular ou circular, seguindo a forma do mapa. Default: " +"Tamanho do Mapa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr "" +" - {cc}DistanciaMin{ci}: a distancia minima entre dois pontos de spawn. " +"Default: 250 Blocos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr "" +" - {cc}Numero de Spawns{ci}: o numero de pontos a gerar. Default: o numero " +"de jogadores ou equipas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr "" +" - {cc}xCentro{ci}, {cc}zCentro{ci}: o centro da regiao onde os pontos sao " +"gerados. Default: Spawn do Mundo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr " - {cc}Mundo{ci}: o mundo onde os pontos de spawn vao ser gerados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "" +"{cc}/uh spawns generate {ci}: gera automaticamente os pontos spawns. Faz /uh" +" spawns generate para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "" +"{cc}/uh spawns dump {ci}: mostra os pontos de spawn num formato exportavel. " +"{gray}Pode ser usado em alguns sites para ver os pontos de Spawn, por " +"exemplo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "{ce}Nao esta nenhum Ponto de Spawn registado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "{ci}Estao {0} Pontos de Spawn registados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "{lightpurple}Mundo {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:180 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "{cc}/uh spawns list {ci}: lista dos pontos de spawn registados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "{cs}TODOS os Pontos de Spawn foram Removidos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "" +"{cc}/uh spawns reset {ci}: remove todos os pontos de spawn registados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "{cs}O Ponto de Spawn {1};{2} no Mundo {0} foi Removido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" +"{cc}/uh spawns remove [<x> <z>] {ci}: remove pontos de spawn com as " +"coordenadas inseridas, ou o local onde o comando e executado se nao forem " +"inseridas coordenadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:110 +msgid "{ce}The player {0} is not online." +msgstr "{ce}{0} esta OFFLINE." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "{ce}Nao existe ponto de Morte para {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "{cs}O Jogador {0} foi teleportado para o local da sua Morte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "" +"{ce}{0} nao foi teleportado porque nao foi encontrado um local seguro para o" +" mesmo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "" +"{ci}Usa {cc}/uh tpback {0} force{ci} para teleportar o Jogador mesmo que o " +"local nao seja seguro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "" +"{cc}/uh tpback <jogador> [force] {ci}: teleporta em seguranca um jogador " +"para o local da sua morte. Quando especificado - force - teleporta mesmo que" +" nao seja seguro." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "{ce}O Jogo ainda nao comecou!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "{ce}Nao esta so uma Equipa Viva!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "" +"{cc}/uh finish {ci}: Exibe o nome do(s) Vencedor(es) e lanca alguns " +"foguetes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this" +" point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his" +" spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "{ce}Este Jogador nao esta a Jogar ou esta MORTO!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "" +"{cs}Porque {0} esta OFFLINE, vamos ressuscita lo quando ele ficar ONLINE. Se" +" estava Banido, ja nao esta." + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "{ce}{0} nao esta MORTO!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "{cc}/uh resurrect <jogador> {ci}: ressuscita o jogador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:111 +msgid "" +"{ce}Unable to add the player {0} to the team {1}. This player is unknown in " +"the server." +msgstr "{ce}Impossivel adicionar {0} a Equipa {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:119 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "{ce}Esta Equipa nao Existe." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:132 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "{cs}O Jogador {0} foi adicionado com Sucesso a Equipa {1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:178 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" +"{cc}/uh team join <jogador> <equipa ...>{ci}: adiciona um jogador a uma " +"equipa. O nome da equipa pode ser a cor ou o seu determinado nome." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "{cs}Todas as Equipas foram Removidas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "{cc}/uh team reset {ci}: elimina todas as equipas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "" +"{ce}Impossivel criar a Equipa, verifica o nome da cor. Dica: usa Tab para " +"auto completar." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:122 +msgid "{cs}Team {0}{cs} added." +msgstr "{cs}Equipa {0}{cs} adicionada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:164 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "" +"{cc}/uh team add <cor> [<nome ...>]{ci}: adiciona uma equipa com uma " +"determinada cor." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:90 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "{ce}O Jogador {0} esta OFFLINE!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:107 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "{cs}O Jogador {0} foi removido com Sucesso da sua Equipa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:141 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "{cc}/uh team leave <jogador> {ci}: retira um jogador da sua equipa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "{cs}Equipa {0} Eliminada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "{cc}/uh team remove <nome ...> {ci}: elimina uma equipa" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "{ce}Nao existe nenhuma Equipa para ser mostrada." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "{0} ({1} Jogador)" +msgstr[1] "{0} ({1} Jogadores)" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "{cc}/uh team list {ci}: lista das equipas e seus jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "{aqua}------ Comandos para os Temporizadores ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "" +"{cc}/uh timers {ci}: controla os temporizadores. Faz /uh timers para " +"detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:106 +msgid "{aqua}------ Team commands ------" +msgstr "{aqua}------ Comandos para Equipas ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:107 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the" +" given team. Without arguments, displays the chat-based team selector." +msgstr "" +"{cc}/join [jogador] <equipa ...> {ci}: adiciona o “jogador” (ou quem " +"executou) na Equipa. Sem argumentos (/join), aparece um selecionador de " +"equipas baseado ." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:108 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "" +"{cc}/leave [jogador] {ci}: remove o “jogador” (ou quem executou) da sua " +"Equipa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:115 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "{cc}/uh team {ci}: edita as equipas. Faz /uh team para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "{aqua}------ Comandos para Limites ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "{cc}/uh border {ci}: edita os limites. Faz /uh border para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "{ce}Hey, isso nao e um numero de meios-coracoes. Isso e Texto. Pfff." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "{ce}Assassino em Serie!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "{ce}A Vida de {0} nao foi atualizada para evitar a sua Morte." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "" +"{cc}/uh healall [meios-coracoes=20|±diferenca] {ci}: regenera todos os " +"jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "Console" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "" +"{ce}Nao podes passar para o proximo episodio porque o Jogo ainda nao " +"Comecou." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "{cc}/uh shift {ci}: passa para o proximo episodio." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "{cst}A Gerar os Limites..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "{ci}Apartir do Console, a gerar os limites para o mundo Default, {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the" +" config are probably invalid." +msgstr "" +"{ce}Impossivel Gerar os Limites: ve os logs para detalhes. Os blocos " +"colocados nas configuracoes sao provavelmente invalidos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "{ce}Ocorreu um Erro, ve a Console para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "{cst}Limites Criados com Sucesso." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "" +"{cc}/uh generatewalls {ci}: gera as paredes, segundo as configuracoes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "{ce}Este temporizador nao esta registado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "{cs}O temporizador {0}{cs} foi Parado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "" +"{cc}/uh timers stop <titulo ...> {ci}: para um temporizador. O temporizador " +"e removido do scoreboard." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "{cs}O temporizador {0}{cs} foi Iniciado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "{cc}/uh timers start <titulo ...> {ci}: inicia um temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "{cs}O temporizador {0}{cs} esta agora Oculto." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "" +"{cc}/uh timers hide <titulo ...> {ci}: remove um temporizador do scoreboard." +" Nao para o temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +#, fuzzy +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "{ci}Estao registados {0} temporizadores." +msgstr[1] "{ci}Estao registados {0} temporizadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{yellow} • {ci}{0}{ci} - total {1} segundo - {2}" +msgstr[1] "{yellow} • {ci}{0}{ci} - total {1} segundos - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:81 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{green} • {ci}{0}{ci} - total {1} segundo - {2}" +msgstr[1] "{green} • {ci}{0}{ci} - total {1} segundos - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:90 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "{red} • {ci}{0}{ci} - total {1} segundo" +msgstr[1] "{red} • {ci}{0}{ci} - total {1} segundos" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:119 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "" +"{cc}/uh timers list {ci}: lista de todos os temporizadores registados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "{cs}O temporizador {0}{cs} e agora Exibido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard." +" Automatic when a timer is started." +msgstr "" +"{cc}/uh timers display <titulo ...> {ci}: mostra um temporizador no " +"scoreboard. Automatico quando um temporizador e iniciado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "{cs}O temporizador {0}{cs} foi Removido." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "{cc}/uh timers remove <titulo ...> {ci}: remove um temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "{cs}O temporizador {0}{cs} foi Retomado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "{cc}/uh timers resume <titulo ...> {ci}: retoma o temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "{cs}A Duracao do temporizador {0}{cs} e agora {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or " +"hh:mm:ss." +msgstr "" +"{ce}A Duracao que inseriste e nao e valida. Os formatos que podes utilizar " +"sao mm ou mm:ss ou hh:mm:ss." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a " +"timer." +msgstr "" +"{cc}/uh timers set <duration> <titulo ...> {ci}: muda a duracao de um " +"temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "{ce}Um temporizador com o nome {0}{ce} ja existe; escolhe outro nome." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "{cs}O temporizador {0}{cs} (duracao {1}) foi adicionado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "" +"{cc}/uh timers add <duracao> <titulo ...> {ci}: adiciona um temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "{cs}O temporizador {0}{cs} foi Pausado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "{cc}/uh timers pause <titulo ...> {ci}: pausa um temporizador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "{cst}Foste Congelado por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "{cst}Foste Descongelado por {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "{cs}{0} esta agora Congelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "{cs}{0} esta agora Descongelado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "{darkaqua}O Jogo esta agora PARADO." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "{darkaqua}O Jogo foi Retomado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "{aqua}------ Comandos para Congelar/Parar ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "" +"{cc}/uh freeze on [jogador]{ci}: congela um jogador, ou a si proprio se nao " +"tiver jogador especificado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if" +" the entire game is frozen." +msgstr "" +"{cc}/uh freeze off [jogador]{ci}: descongela um jogador (ou a si), mesmo com" +" o Jogo parado." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "" +"{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "" +"{cc}/uh freeze all{ci}: congela/pausa o Jogo Todo (jogadores, mobs, tempo)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this" +" in order to relaunch the timer." +msgstr "" +"{cc}/uh freeze none{ci}: descongela/retoma o Jogo Todo. PRECISAS de fazer " +"este comando para Retomar o tempo do Jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "" +"{cc}/uh freeze {ci}: (Des)Congela o Jogo todo, ou a um jogador. Faz /uh " +"freeze para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "{ce}Este Jogador esta OFFLINE." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "" +"{ce}Nao podes MATAR Jogadores com este comando, para evitar falhas na " +"escrita." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "" +"{cc}/uh heal <jogador> [meios-coracoes=20|±diferenca] {ci}: regenera vida de" +" um jogador para os meio-coracoes indicados (default 20)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" +"{cc}/uh feed <jogador> [Fome=20] [Saturacao=max] {ci}: alimenta os " +"jogadores." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "{ce}Este jogador nunca foi visto neste server." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "{cs}O Jogador {0} foi marcado como Morto." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "{ce}{0} nao e um jogador vivo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "" +"{cc}/uh kill <jogador> {ci}: marca um jogador como morto, mesmo que esteja " +"offline." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:102 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the" +" game." +msgstr "" +"{ce}O Jogo ja comecou! Faz Reload ou Reinicia o server para reiniciar o " +"Jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:150 +msgid "{aqua}------ Beginning of the game ------" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:151 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:152 +msgid "{aqua}Startup options" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:153 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append" +" them to the command with spaces." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:154 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:155 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:162 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "{cc}/uh start {ci}: prepara o Jogo." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:94 +msgid "{cs}The player {0} is now a spectator." +msgstr "{cs}{0} esta agora em Modo Espectador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:115 +msgid "{cs}The player {0} is now a player." +msgstr "{cs}{0} e agora um Jogador. Modo Espectador Desativado" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:125 +msgid "{ce}There isn't any spectator to list." +msgstr "{ce}Nao existe nenhum Espectador." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "{ci}{0} Espectador registado." +msgstr[1] "{ci}{0} Espectadores registados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:130 +msgid "{ci}This count includes only the initial spectators." +msgstr "{ci}Este numero inclui apenas os Espectadores Iniciais." + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "{lightpurple} - {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:171 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "{aqua}------ Comandos Espectadores Iniciais ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:173 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "" +"{cc}/uh spec add <jogador>{ci}: adiciona um espectador inicial (nao ira " +"jogar)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:174 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "{cc}/uh spec remove <jogador>{ci}: remove um espectador inicial." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:175 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "{cc}/uh spec list{ci}: lista dos espectadores iniciais." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:183 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "{cc}/uh spec {ci}: edita os espectadores. Faz /uh spec para detalhes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "{cs}Estas agora a falar apenas com a tua Equipa." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "{cs}Estas agora a falar com Todos." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "{cs}Estas agora a falar com a Equipa {0}{cs}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed " +"...>{ci}." +msgstr "" +"{ci}Legenda: {cc}/uh command <necessario> [opcional=default] <espacos sao " +"validos ...>{ci}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "{ce}Nao estas Autorizado a executar este comando." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +msgid "" +"{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "{ce}Estas fora do Futuro Limite de diametro {0}." +msgstr[1] "{ce}Estas fora do Futuro Limite de diametro {0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "{ce}Estas fora dos Futuros Limtes de {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "{ci}Tens de andar {0} bloco para estares dentro dos Novos Limites." +msgstr[1] "{ci}Tens de andar {0} blocos para estares dentro dos Novos Limites." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:325 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "{ce}Impossivel Comecar o Jogo: pontos de Spawn insuficientes." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:326 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:399 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "{lightpurple}Teleporte em Progresso... Espera um Pouco." + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:414 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:434 +msgid "{gray}Player {0}{gray} teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:486 +msgid "{cs}All teams are teleported." +msgstr "{cs}Todas as Equipas foram Teleportadas." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:487 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "{gray}Usa {cc}/uh start{gray} para comecar o Jogo." + +#. Displayed in the action bar when the slow teleportation is finished but the +#. game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:525 +msgid "{ce}Please execute {cc}/uh start slow{ce} before." +msgstr "{ce}Faz {cc}/uh start slow{ce} antes desse Comando." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:531 +msgid "{ce}Please wait while the players are teleported." +msgstr "{ce}Espera ate os jogadores estarem todos teleportados." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:631 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "" + +#. The "and" in the winners players list (like "player1, player2 and +#. player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1083 +msgctxt "winners_list" +msgid "and" +msgstr "e" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1095 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Parabens a {0} (da Equipa {1}{green}) pela " +"sua Vitoria! {darkgreen}{obfuscated}--" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1099 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green} Parabens a {0} pela sua Vitoria! " +"{darkgreen}{obfuscated}--" + +#. The main title of the /title displayed when a team wins the game. {0} +#. becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in +#. solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1118 +msgid "{darkgreen}{0}" +msgstr "" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes +#. the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1113 +msgid "{green}This team wins the game!" +msgstr "" + +#. The subtitle of the /title displayed when a player wins the game (in solo). +#. {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1120 +msgid "{green}wins the game!" +msgstr "" diff --git a/src/main/resources/i18n/pt_PT.yml b/src/main/resources/i18n/pt_PT.yml deleted file mode 100644 index 0c22915..0000000 --- a/src/main/resources/i18n/pt_PT.yml +++ /dev/null @@ -1,498 +0,0 @@ -author: "João Roda" -keys: - load: - spawnPointAdded: "Ponto de Spawn {0},{1} adicionado a partir das configuracoes" - invalidSpawnPoint: "Ponto de Spawn invalido nas configuracoes: {0}" - teamAdded: "Equipa {0} adicionada a partir das configuracoes" - namedTeamAdded: "Equipa {0} ({1}) adicionada a partir das configuracoes" - invalidTeam: "Equipa invalida nas configuracoes: {0}" - recipeApple: "Adicionado nova receita para Maca Dourada." - recipeCompass: "Adicionado nova receita para Bussola." - recipeMelon: "Adicionado nova receita para Melancia Reluzente." - loaded: "Ultra Hardcore plugin Carregado." - - WBNotInstalled1: "{darkred}[UHC] {ce}WorldBorder nao esta instalado: paredes nao serao verificadas!" - WBNotInstalled2: "{gray}Tambem, sem WorldBorder, as paredes nao podem ser diminuidas em Jogo (Avisos excluidos)." - WBNotInstalled3: "{gray}Instala so o plugin; UHPlugin automaticamente o configura." - - SPNotInstalled1: "{darkred}[UHC] {ce}SpectatorPlus nao esta instalado." - SPNotInstalled2: "{gray}Se queres um Modo de Espectador, instala o Plugin; UHPlugin automaticamente o configura." - - PLNotInstalled1: "{darkred}[UHC] {ce}ProtocolLib e preciso mas nao esta instalado!" - PLNotInstalled2: "{gray}As seguintes opcoes precisam do ProtocolLib:" - PLNotInstalledItem: "{darkgray} - {gray}{0}" - PLNotInstalled3: "{gray}ProtocolLib esta disponivel aqui: {0}" - - cmd: - errorLoad: "{ce}Ocorreu um Erro, ve a console para detalhes. Provavelmente sera um Bug." - errorUnknown: "{ce}Este comando nao existe. Faz /uh para veres os comandos existentes." - errorUnauthorized: "{ce}Nao estas Autorizado a executar este comando." - - titleHelp: "{yellow}{0} - versao {1}" - legendHelp: "{ci}Legenda: {cc}/uh command <necessario> [opcional=default] <espacos sao validos ...>{ci}." - helpNextPage: "{gray}Proxima Pagina: /uh {0}" - - titleGameCmd: "{aqua}------ Comandos de Jogo ------" - helpStart: "{cc}/uh start {ci}: prepara o Jogo." - helpStartSlow: "{cc}/uh start slow {ci}: prepara o Jogo devagar, em 2 etapas, para servers pequenos." - helpShift: "{cc}/uh shift {ci}: passa para o proximo episodio." - helpTeam: "{cc}/uh team {ci}: edita as equipas. Faz /uh team para detalhes." - helpSpawns: "{cc}/uh spawns {ci}: gere os pontos de spawn. Faz /uh spawns para detalhes." - helpSpec: "{cc}/uh spec {ci}: edita os espectadores. Faz /uh spec para detalhes." - helpWall: "{cc}/uh generatewalls {ci}: gera as paredes, segundo as configuracoes." - helpBorder: "{cc}/uh border {ci}: edita os limites. Faz /uh border para detalhes." - - titleBugCmd: "{aqua}------ Comandos para Bugs ------" - helpHeal: "{cc}/uh heal <jogador> [meios-coracoes=20|±diferenca] {ci}: regenera vida de um jogador para os meio-coracoes indicados (default 20)." - helpHealall: "{cc}/uh healall [meios-coracoes=20|±diferenca] {ci}: regenera todos os jogadores." - helpFeed: "{cc}/uh feed <jogador> [Fome=20] [Saturacao=max] {ci}: alimenta os jogadores." - helpFeedall: "{cc}/uh feedall [Fome=20] [Saturacao=max] {ci}: alimenta todos os jogadores." - helpKill: "{cc}/uh kill <jogador> {ci}: marca um jogador como morto, mesmo que esteja offline." - helpResurrect: "{cc}/uh resurrect <jogador> {ci}: ressuscita o jogador." - helpTpback: "{cc}/uh tpback <jogador> [force] {ci}: teleporta em seguranca um jogador para o local da sua morte. Quando especificado - force - teleporta mesmo que nao seja seguro." - - titleMiscCmd: "{aqua}------ Outros Comandos ------" - helpFreeze: "{cc}/uh freeze {ci}: (Des)Congela o Jogo todo, ou a um jogador. Faz /uh freeze para detalhes." - helpFinish: "{cc}/uh finish {ci}: Exibe o nome do(s) Vencedor(es) e lanca alguns foguetes." - helpTP: "{cc}/uh tp {ci}: teleporta os Espectadores ou uma Equipa inteira. Faz /uh tp para detalhes." - helpTimers: "{cc}/uh timers {ci}: controla os temporizadores. Faz /uh timers para detalhes." - helpInfos: "{cc}/uh infos {ci}: apresenta algumas infos sobre o jogo que esta a decorrer." - helpAbout: "{cc}/uh about {ci}: informacao sobre o Plugin e as Traducoes." - - teamHelpTitle: "{aqua}------ Comandos para Equipas ------" - teamHelpAdd: "{cc}/uh team add <cor> {ci}: adiciona uma equipa com uma determinada cor." - teamHelpAddName: "{cc}/uh team add <cor> <nome ...> {ci}: adiciona uma equipa com um determinado nome e cor. Podem ser usados espacos." - teamHelpRemove: "{cc}/uh team remove <nome ...> {ci}: elimina uma equipa" - teamHelpJoin: "{cc}/uh team join <jogador> <equipa ...>{ci}: adiciona um jogador a uma equipa. O nome da equipa pode ser a cor ou o seu determinado nome." - teamHelpLeave: "{cc}/uh team leave <jogador> {ci}: retira um jogador da sua equipa." - teamHelpList: "{cc}/uh team list {ci}: lista das equipas e seus jogadores." - teamHelpReset: "{cc}/uh team reset {ci}: elimina todas as equipas." - teamHelpJoinCmd: "{cc}/join [jogador] <equipa ...> {ci}: adiciona o “jogador” (ou quem executou) na Equipa. Sem argumentos (/join), aparece um selecionador de equipas baseado ." - teamHelpLeaveCmd: "{cc}/leave [jogador] {ci}: remove o “jogador” (ou quem executou) da sua Equipa." - - spawnsHelpTitle: "{aqua}------ Comandos para os Spawns ------" - spawnsHelpAdd: "{cc}/uh spawns add {ci}: adiciona um ponto de spawn para uma equipa ou jogador, no local onde e executado." - spawnsHelpAddXZ: "{cc}/uh spawns add <x> <z> {ci}: adiciona um ponto de spawn para uma equipa ou jogador, nas coordenadas inseridas, no Mundo Default." - spawnsHelpGenerate: "{cc}/uh spawns generate {ci}: gera automaticamente os pontos spawns. Faz /uh spawns generate para detalhes." - spawnsHelpGenerateDetailsCmdTitle: "{aqua}Comando" - spawnsHelpGenerateDetailsCmd: "{cc}/uh spawns generate <circular|grid|random> [Tamanho] [DistanciaMin] [Numero de Spawns] [xCentro] [zCentro] [Mundo]" - spawnsHelpGenerateDetailsShapesTitle: "{aqua}Formatos" - spawnsHelpGenerateDetailsShapesRandom: " - {cc}random{ci}: gera pontos de spawns ao calhas no mapa, com uma distancia minima entre eles." - spawnsHelpGenerateDetailsShapesGrid: " - {cc}grid{ci}: gera pontos de spawn em quadrados concentricos, com uma distancia constante entre dois pontos de spawn." - spawnsHelpGenerateDetailsShapesCircular: " - {cc}circular{ci}: gera pontos de spawn em circulos concentricos, com uma distancia minima entre dois pontos. Em cada circulo, o angulo (e a sua distancia) entre dois pontos e constante." - spawnsHelpGenerateDetailsArgsTitle: "{aqua}Argumentos" - spawnsHelpGenerateDetailsArgsSize: " - {cc}Tamanho{ci}: o tamanho da regiao onde os pontos de spawn vao ser gerados. Quadrangular ou circular, seguindo a forma do mapa. Default: Tamanho do Mapa." - spawnsHelpGenerateDetailsArgsDistanceMin: " - {cc}DistanciaMin{ci}: a distancia minima entre dois pontos de spawn. Default: 250 Blocos." - spawnsHelpGenerateDetailsArgsCount: " - {cc}Numero de Spawns{ci}: o numero de pontos a gerar. Default: o numero de jogadores ou equipas." - spawnsHelpGenerateDetailsArgsCenter: " - {cc}xCentro{ci}, {cc}zCentro{ci}: o centro da regiao onde os pontos sao gerados. Default: Spawn do Mundo." - spawnsHelpGenerateDetailsArgsWorld: " - {cc}Mundo{ci}: o mundo onde os pontos de spawn vao ser gerados." - spawnsHelpList: "{cc}/uh spawns list {ci}: lista dos pontos de spawn registados." - spawnsHelpDump: "{cc}/uh spawns dump {ci}: mostra os pontos de spawn num formato exportavel. {gray}Pode ser usado em alguns sites para ver os pontos de Spawn, por exemplo." - spawnsHelpRemove: "{cc}/uh spawns remove [<x> <z>] {ci}: remove pontos de spawn com as coordenadas inseridas, ou o local onde o comando e executado se nao forem inseridas coordenadas." - spawnsHelpReset: "{cc}/uh spawns reset {ci}: remove todos os pontos de spawn registados." - - specHelpTitle: "{aqua}------ Comandos Espectadores Iniciais ------" - specHelpNoticeSpectatorPlusNotInstalled: "{ce}Atencao{ci}: como o SpectatorPlus nao esta instalado, um espectador e {italic}apenas{ci} um jogador ignorado (sem vanish)." - specHelpAdd: "{cc}/uh spec add <jogador>{ci}: adiciona um espectador inicial (nao ira jogar)." - specHelpRemove: "{cc}/uh spec remove <jogador>{ci}: remove um espectador inicial." - specHelpList: "{cc}/uh spec list{ci}: lista dos espectadores iniciais." - - freezeHelpTitle: "{aqua}------ Comandos para Congelar/Parar ------" - freezeHelpOn: "{cc}/uh freeze on [jogador]{ci}: congela um jogador, ou a si proprio se nao tiver jogador especificado." - freezeHelpOff: "{cc}/uh freeze off [jogador]{ci}: descongela um jogador (ou a si), mesmo com o Jogo parado." - freezeHelpAll: "{cc}/uh freeze all{ci}: congela/pausa o Jogo Todo (jogadores, mobs, tempo)." - freezeHelpNone: "{cc}/uh freeze none{ci}: descongela/retoma o Jogo Todo. PRECISAS de fazer este comando para Retomar o tempo do Jogo." - - borderHelpTitle: "{aqua}------ Comandos para Limites ------" - borderHelpCurrent: "{cc}/uh border current{ci}: diz o tamanho dos limites atuais." - borderHelpSet: "{cc}/uh border set <tamanho> [force]{ci}: muda o limite das paredes. Se nao for indicado o force, a operacao sera cancelada se tiver algum jogador fora dos novos limites." - borderHelpWarning: "{cc}/uh border warning <tamanhofuturo> [minutos para a reducao]{ci}: avisa todos os jogadores fora dos futuros limites. E so um AVISO, nao acontece nada." - borderHelpWarningCancel: "{cc}/uh border warning cancel{ci}: cancela os avisos do /uh border warning." - borderHelpCheck: "{cc}/uh border check <tamanho>{ci}: faz uma lista dos jogadores fora dos limites dados." - - tpHelpTitle: "{aqua}------ Comandos para Teleporte ------" - tpHelpTeam: "{cc}/uh tp team <x> <y> <z> | <jogador> <equipa ...> {ci}: teleportar uma equipa para um local ou jogador." - tpHelpSpectators: "{cc}/uh tp spectators <x> <y> <z> | <jogador> {ci}: teleporta os espectadores (tal como os jogadores mortos) para um local ou jogador." - - timersHelpTitle: "{aqua}------ Comandos para os Temporizadores ------" - timersHelpAdd: "{cc}/uh timers add <duracao> <titulo ...> {ci}: adiciona um temporizador." - timersHelpSet: "{cc}/uh timers set <duration> <titulo ...> {ci}: muda a duracao de um temporizador." - timersHelpDisplay: "{cc}/uh timers display <titulo ...> {ci}: mostra um temporizador no scoreboard. Automatico quando um temporizador e iniciado." - timersHelpHide: "{cc}/uh timers hide <titulo ...> {ci}: remove um temporizador do scoreboard. Nao para o temporizador." - timersHelpStart: "{cc}/uh timers start <titulo ...> {ci}: inicia um temporizador." - timersHelpPause: "{cc}/uh timers pause <titulo ...> {ci}: pausa um temporizador." - timersHelpResume: "{cc}/uh timers resume <titulo ...> {ci}: retoma o temporizador." - timersHelpStop: "{cc}/uh timers stop <titulo ...> {ci}: para um temporizador. O temporizador e removido do scoreboard." - timersHelpRemove: "{cc}/uh timers remove <titulo ...> {ci}: remove um temporizador." - timersHelpList: "{cc}/uh timers list {ci}: lista de todos os temporizadores registados." - timersHelpDurations: "{gray}'<duracao>' formato : mm, mm:ss ou hh:mm:ss." - - about: - authors: "Plugin feito com amor por {0}." - and: "e" - build: - number: "Numero da Build: {0}." - notAvailable: "Numero de Build nao Disponivel." - i18n: - title: "{aqua}------ Traducoes ------" - selected: "Linguagem Selecionada: {0} (traduzido por {1})." - fallback: "Linguagem para Erros: {0} (traduzido por {1})." - license: - title: "{aqua}------ Licenca ------" - license: "Publicado sobre a GNU General Public License (versao 3)." - - start: - already: "{ce}O Jogo ja comecou! Faz Reload ou Reinicia o server para reiniciar o Jogo." - syntax: "{ce}Syntax Error. Usa: /uh start [slow] ou /uh start slow go." - - notEnoughTP: "{ce}Impossivel Comecar o Jogo: pontos de Spawn insuficientes." - - teleportationInProgress: "{lightpurple}Teleporte em Progresso... Espera um Pouco." - startSlowBeforeStartSlowGo: "{ce}Faz {cc}/uh start slow{ce} antes desse Comando." - startSlowWaitBeforeGo: "{ce}Espera ate os jogadores estarem todos teleportados." - startSlowTeamTP: "{gray}Equipa {0}{gray} Teleportada." - startSlowAllTeamsTP: "{cs}Todas as Equipas foram Teleportadas." - startSlowAllTeamsTPCmd: "{gray}Usa {cc}/uh start slow go{gray} para comecar o Jogo." - - go: "{green}----- GO GO GO -----" - - finish: - notStarted: "{ce}O Jogo ainda nao comecou!" - notFinished: "{ce}Nao esta so uma Equipa Viva!" - - and: "e" - - broadcast: - withTeams: "{darkgreen}{obfuscated}--{green} Parabens a {0} (da Equipa {1}{green}) pela sua Vitoria! {darkgreen}{obfuscated}--" - withoutTeams: "{darkgreen}{obfuscated}--{green} Parabens a {0} pela sua Vitoria! {darkgreen}{obfuscated}--" - - episodes: - end: "{aqua}-------- Fim do Episodio {0} --------" - endForced: "{aqua}-------- Fim do Episodio {0} [forcado por {1}] --------" - - scoreboard: - episode: "{gray}Episodio {white}{0}" - players: "{white}{0}{gray} Jogadores" - teams: "{white}{0}{gray} Equipas" - timer: "{white}{0}{gray}:{white}{1}" - timerWithHours: "{0}{gray}:{white}{1}{gray}:{white}{2}" - - motd: - beforeStart: "A Espera de Jogadores..." - starting: "A Comecar..." - runningSolo: "Jogo a Decorrer! {0} jogadores vivos." - runningTeams: "Jogo a Decorrer! {0} jogadores vivos em {1} equipas." - finishedSolo: "Jogo Terminou; Parabens a {0} pela sua Vitoria!" - finishedTeams: "Jogo Terminou; A Equipa {0} ganhou o Jogo!" - - death: - kickMessage: "Foste MORTO!" - banMessage: "Foste MORTO!" - teamHasFallen: "{0}A Equipa {1} foi extinguida!" - - canRespawn: "{darkpurple}{obfuscated}----{lightpurple}{italic} PODES RENASCER{lightpurple}, clica em {italic}Renascer {lightpurple}no proximo ecra." - - craft: - goldenApple: - loreLine1Player: "Feita da cabeca" - loreLine2Player: "de {0}" - loreLine1Monster: "Feita da cabeca" - loreLine2Monster: "de uma coisa Horrivel" - nameGoldenAppleFromHeadNormal: "{aqua}Maca Dourada" - nameGoldenAppleFromHeadNotch: "{lightpurple}Maca Dourada" - - compass: - noRottenFlesh: "{gray}{italic}Precisas de Carne Podre para utilizares a Bussola." - nothingFound: "{gray}{italic}Nao foram encontrados jogadores por perto." - success: "{gray}A Bussola aponta agora para o jogador mais proximo." - - dynmap: - markerLabelDeath: "Ponto de Morte de {0}" - markerLabelSpawn: "Ponto de Spawn da Equipa {0}" - markerLabelSpawnNoTeam: "Ponto de Spawn de {0}" - - wall: - startGen: "{cst}A Gerar os Limites..." - consoleDefaultWorld: "{ci}Apartir do Console, a gerar os limites para o mundo Default, {0}" - error: "{ce}Impossivel Gerar os Limites: ve os logs para detalhes. Os blocos colocados nas configuracoes sao provavelmente invalidos." - unknownError: "{ce}Ocorreu um Erro, ve a Console para detalhes." - blocksError: "Impossivel construir os Limites, os blocos nas configuracoes sao invalidos." - done: "{cst}Limites Criados com Sucesso." - - spawns: - NaN: "{ce}Isto nao e um numero!" - syntaxError: "{ce}Syntax error; Faz /uh spawns." - errorCoords: "{ce}Tens de especificar as coordenadas a partir da Console." - error2Coords: "{ce}Precisas de especificar pelo menos duas coordenadas." - - add: - added: "{cs}Ponto de Spawn adicionado no Mundo {0}: {1};{2}" - outOfLimits: "{ce}Nao podes adicionar um ponto de spawn fora dos Limites." - noSafeSpot: "{ce}Impossivel adicionar este ponto de Spawn: nao foi encontrado um ponto de spawn no Nether." - - assumptions: - solo: "{ci}Nenhuma EQUIPA encontrada. Assumindo que o jogo e em modo SOLO." - partialSolo: "{ci}Alguns jogadores nao estao em nenhuma equipa; ficarao a jogar sozinhos; foram adicionados ao numero de Pontos de Spawn necessarios." - - generate: - nothingToDo: "{ci}Pediste uma geracao nula. Portanto, nao foram gerados pontos de spawn." - unsupportedMethod: "{ce}O Metodo de geração “{0}” nao e (ainda?) suportada." - unknownWorld: "{ce}O Mundo {0} nao existe." - success: "{cs}Pontos de Spawn gerados com sucesso." - impossible: "{ce}Pediste o Impossivel: existem demasiados pontos de spawn no espaco muito pequeno. Diminui os pontos de spawn ou o espaco minimo entre dois pontos." - - list: - nothing: "{ce}Nao esta nenhum Ponto de Spawn registado." - count: "{ci}Estao {0} Pontos de Spawn registados." - world: "{lightpurple}Mundo {0}" - item: - overworld: "{green}{0}{darkgreen};{green}{1}" - nether: "{red}{0}{darkred};{red}{1}" - end: "{yellow}{0}{gold};{yellow}{1}" - other: "{gray}{0}{darkgray};{gray}{1}" - - remove: - removed: "{cs}O Ponto de Spawn {1};{2} no Mundo {0} foi Removido." - - reset: "{cs}TODOS os Pontos de Spawn foram Removidos." - - team: - syntaxError: "{ce}Syntax Error. Usa: /uh team para veres os Comandos." - unknownCommand: "{ce}Comando Desconhecido. Faz /uh team para Comandos Validos." - onlyAsAPlayer: "{ce}Este comando so pode ser executado, desta maneira, por um jogador." - - add: - errorColor: "{ce}Impossivel criar a Equipa, verifica o nome da cor. Dica: usa Tab para auto completar." - errorExists: "{ce}Esta Equipa ja existe." - added: "{cs}Equipa {0}{cs} adicionada." - - remove: - doesNotExists: "{ce}Esta Equipa nao Existe." - removed: "{cs}Equipa {0} Eliminada." - - addplayer: - disconnected: "{ce}Impossivel adicionar {0} a Equipa {1}." - success: "{cs}O Jogador {0} foi adicionado com Sucesso a Equipa {1}" - added: "{aqua}Estas agora na {aqua}Equipa {reset}{0}." - doesNotExists: "{ce}Esta Equipa nao Existe." - full: "{ce}A Equipa {0}{ce} esta Completa!" - - joinhelp: "{ce}Usa: {cc}/join [jogador] <Equipa>{ce}." - - removeplayer: - disconnected: "{ce}O Jogador {0} esta OFFLINE!" - success: "{cs}O Jogador {0} foi removido com Sucesso da sua Equipa." - removed: "{darkaqua}Tu ja nao fazes parte da Equipa {0}{darkaqua}." - - list: - nothing: "{ce}Nao existe nenhuma Equipa para ser mostrada." - itemTeam: "{0} ({1} Jogadores)" - - bulletPlayerOnline: "{green} • " - bulletPlayerOffline: "{red} • " - - itemPlayer: "{0}" - - gui: - choose: "{gold}Clica nos nomes em baixo para juntar a uma equipa" - playersCount: "{gray}[{white}{0}{gray}/{white}{1}{gray}]" - playersCountUnlimited: "{gray}[{white}{0}{gray}]" - tooltipCount: "{0} jogador(es) nesta equipa" - tooltipJoin: "Clica aqui para juntares a equipa {0}" - tooltipJoinInside: "Estas agora na Equipa {0}" - leaveTeam: "{darkred}[\u00D7] {red}Clica aqui para saires da tua Equipa" - howToDisplayAgain: "{gray}Faz /join para mostrar isto outra vez." - noTeams: "{ce}Nao ha nenhuma Equipa registada." - - reset: - success: "{cs}Todas as Equipas foram Removidas." - - message: - noConsole: "{ce}Nao podes enviar uma mensagem de Equipa a partir da Console." - noTeam: "{ce}Nao estas em nenhuma Equipa!" - usage: "{ce}Usa: /{0} <mensagem>" - - notAllowed: - self: "{ce}Nao te e permitido enviar mensagens privadas para a tua Equipa." - others: "{ce}Nao te e permitido entrar no chat privado de outra equipa." - - toggle: - nowTeamChat: "{cs}Estas agora a falar apenas com a tua Equipa." - nowGlobalChat: "{cs}Estas agora a falar com Todos." - - nowOtherTeamChat: "{cs}Estas agora a falar com a Equipa {0}{cs}." - unknownTeam: "{ce}Esta Equipa nao existe." - - format: "{gold}[{0}{gold} -> Equipa] {reset}{1}" - formatOtherTeam: "{gold}[{0}{gold} -> Equipa {1}{gold}] {reset}{2}" - - infos: - notStarted: "{ci}O Jogo ainda nao comecou." - players: "{ci}{0} jogadores vivos em {1} teams." - - bulletOnline: "{green} • " - bulletOffline: "{red} • " - - separatorAliveState: "{gray} - " - - dead: "{red}Morto" - alive: "{green}Vivo" - - tooltips: - online: "Atualmente Online" - offline: "Atualmente Offline " - - team: "Equipa: {0}" - - health: "{0} meios-coracoes" - - shift: - consoleName: "Console" - cantNotStarted: "{ce}Nao podes passar para o proximo episodio porque o Jogo ainda nao Comecou." - - heal: - usage: "{ce}Usa: /uh heal <jogador> [numero de Meios-Coracoes = 20]" - offline: "{ce}Este Jogador esta OFFLINE." - errorNaN: "{ce}Hey, isso nao e um numero de meios-coracoes. Isso e Texto. Pfff." - errorNoKill: "{ce}Nao podes MATAR Jogadores com este comando, para evitar falhas na escrita." - errorHealthNotUpdatedNoKill: "{ce}A Vida de {0} nao foi atualizada para evitar a sua Morte." - allErrorNoKill: "{ce}Assassino em Serie!" - - feed: - usage: "{ce}Usa: /uh feed <jogador> [Fome = 20] [Saturacao = max]" - offline: "{ce}Este jogador esta Offline." - errorNaN: "{ce}Fome e Saturacao tem de ser numeros!" - - kill: - usage: "{ce}Usa : /uh kill <jogador>" - neverPlayed: "{ce}Este jogador nunca foi visto neste server." - notAlive: "{ce}{0} nao e um jogador vivo." - killed: "{cs}O Jogador {0} foi marcado como Morto." - - resurrect: - usage: "{ce}Usa: /uh resurrect <jogador>" - unknownOrDead: "{ce}Este Jogador nao esta a Jogar ou esta MORTO!" - offlineOk: "{cs}Porque {0} esta OFFLINE, vamos ressuscita lo quando ele ficar ONLINE. Se estava Banido, ja nao esta." - notDead: "{ce}{0} nao esta MORTO!" - broadcastMessage: "{gold}{0} foi ressuscitado!" - - tpback: - usage: "{ce}Usa: /uh tpback <jogador> [force]" - offline: "{ce}O Jogador {0} nao esta ONLINE." - noDeathLocation: "{ce}Nao existe ponto de Morte para {0}." - teleported: "{cs}O Jogador {0} foi teleportado para o local da sua Morte." - notTeleportedNoSafeSpot: "{ce}{0} nao foi teleportado porque nao foi encontrado um local seguro para o mesmo." - notTeleportedNoSafeSpotCmd: "{ci}Usa {cc}/uh tpback {0} force{ci} para teleportar o Jogador mesmo que o local nao seja seguro." - - tp: - NaN: "{ce}As coordenadas tem que ser tres numeros validos." - targetOffline: "{ce}{0} esta OFFLINE!" - teamDoesNotExists: "{ce}Esta Equipa nao esta Registada." - - spectators: - syntaxError: "{ce}Syntax Error. Usa: /uh spec para detalhes." - unknownCommand: "{ce}Comando Desconhecido. Faz /uh spec para os Comandos Disponiveis." - offline: "{ce}{0} esta OFFLINE." - - add: - success: "{cs}{0} esta agora em Modo Espectador." - - remove: - success: "{cs}{0} e agora um Jogador. Modo Espectador Desativado" - - list: - nothing: "{ce}Nao existe nenhum Espectador." - countSpectators: "{ci}{0} Espectadores registados." - countOnlyInitial: "{ci}Este numero inclui apenas os Espectadores Iniciais." - itemSpec: "{lightpurple} - {0}" - - freeze: - frozen: "{cst}Foste Congelado por {0}." - unfrozen: "{cst}Foste Descongelado por {0}." - playerFrozen: "{cs}{0} esta agora Congelado." - playerUnfrozen: "{cs}{0} esta agora Descongelado." - - playerOnly: "{ce}Precisas de ser um Jogador para fazeres este Comando desta Maneira." - offline: "{ce}{0} esta OFFLINE!" - - scoreboard: "{darkaqua}JOGO PARADO" - - broadcast: - globalFreeze: "{darkaqua}O Jogo esta agora PARADO." - globalUnfreeze: "{darkaqua}O Jogo foi Retomado." - - borders: - syntaxError: "{ce}Syntax Error. Usa: /uh border para detalhes." - NaN: "{ce}“{0}” nao e um Numero..." - - current: - messageSquared: "{ci}O Tamanho atual do Limite e {0}*{0}." - messageCircular: "{ci}O Tamanho atual do Limite Circular e de {0} blocos." - - set: - playersOutsideCanceled: "{ce}Alguns jogadores estao fora dos Futuros Limites. A operacao foi CANCELADA." - playersOutsideCanceledCmd: "{ci}Usa {cc}/uh border set {0} force{ci} para aplicares os Futuros Limites, mesmo com os jogadores Fora dos Limites." - playersOutsideCanceledWarnWorldBorder: "{ce}AVISO: {ci}WorldBorder nao esta Instalado, Jogadores fora dos Limites nao serao Teleportados!" - broadcastSquared: "{lightpurple}O Tamanho dos Limites e agora {0}*{0}." - broadcastCircular: "{lightpurple}O Tamanho do Limte Circular e agora {0} blocos." - - warning: - canceled: "{cs}Avisos Cancelados." - set: "{cs}Limite Futuro Salvo. Todos os Jogadores fora dos Futuros Limites serao avisados a cada {0} segundos." - - messageSquared: "{ce}Estas fora dos Futuros Limtes de {0}*{0}." - messageCircular: "{ce}Estas fora do Futuro Limite de diametro {0}." - - messageDistance: "{ci}Tens de andar {0} blocos para estares dentro dos Novos Limites." - - nameTimer: "Proximos Limites" - - timerUp: "{cs}Acabou o tempo para os Novos Limites!" - - check: - allPlayersInside: "{cs}Todos os Jogadores estao dentro dos Novos Limites." - countPlayersOutside: "{ci}Estao {0} jogadores fora dos Novos Limites." - itemPlayerFar: "{lightpurple} - {red}{0}{ci} (Longe dos Novos Limites)" - itemPlayerClose: "{lightpurple} - {yellow}{0}{ci} (Perto dos Novos Limites)" - itemPlayerVeryClose: "{lightpurple} - {green}{0}{ci} (Muito Perto dos Novos Limites)" - - timers: - syntaxError: "{ce}Syntax error. Usa: /uh timers para detalhes." - durationSyntaxError: "{ce}A Duracao que inseriste e nao e valida. Os formatos que podes utilizar sao mm ou mm:ss ou hh:mm:ss." - timerDoesNotExists: "{ce}Este temporizador nao esta registado." - alreadyExists: "{ce}Um temporizador com o nome {0}{ce} ja existe; escolhe outro nome." - - added: "{cs}O temporizador {0}{cs} (duracao {1}) foi adicionado." - set: "{cs}A Duracao do temporizador {0}{cs} e agora {1}." - displayed: "{cs}O temporizador {0}{cs} e agora Exibido." - hidden: "{cs}O temporizador {0}{cs} esta agora Oculto." - started: "{cs}O temporizador {0}{cs} foi Iniciado." - paused: "{cs}O temporizador {0}{cs} foi Pausado." - resumed: "{cs}O temporizador {0}{cs} foi Retomado." - stopped: "{cs}O temporizador {0}{cs} foi Parado." - removed: "{cs}O temporizador {0}{cs} foi Removido." - - list: - count: "{ci}Estao registados {0} temporizadores." - itemRunning: "{green} • {ci}{0}{ci} - total {1} segundos - {2}" - itemPaused: "{yellow} • {ci}{0}{ci} - total {1} segundos - {2}" - itemStopped: "{red} • {ci}{0}{ci} - total {1} segundos" - - protips: - base: "{darkpurple}Dica!" - - teamchat: - lock: "{gray}Podes usar {cc}/togglechat{gray} para mudar e bloquear o chat entre o chat de Equipa e o chat Global." - useTCommand: "{gray}Para enviares mensagens rapidas para a tua equipa usa {cc}/t <mensagem>{gray}." - useGCommand: "{gray}Para enviares mensagens rapidas para todos usa {cc}/g <mensagem>{gray}." - - crafts: - goldenHead: "{gray}Podes fazer Macas Douradas com cabecas (a mesma maneira mas com uma cabeca em vez de uma maca)." - compassEasy: "{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho de aranha e uma polvora." - compassMedium: "{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho de aranha e uma polvora; no centro, uma enderpearl." - compassHard: "{gray}O Compasso e feito com, nos cantos, um osso, uma carne podre, um olho de aranha e uma polvora; no centro, um olho do fim." - glisteringMelon: "{gray}A melancia reluzente e feita com uma melancia e um bloco de ouro." - noEnchGoldenApple: "{gray}As Macas Douradas Encantadas estao desativadas para este jogo." - - start: - invincibility: "{gray}Caiste numa Arvore? Salta, ainda tens 25 segundos de invencibilidade." diff --git a/src/main/resources/i18n/zh_CN.po b/src/main/resources/i18n/zh_CN.po new file mode 100644 index 0000000..6a9ba23 --- /dev/null +++ b/src/main/resources/i18n/zh_CN.po @@ -0,0 +1,2132 @@ +# Copyright or © or Copr. h404bi (2014 - 2016) +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.0\n" +"Report-Msgid-Bugs-To: h404bi\n" +"POT-Creation-Date: 2016-01-20 03:37+0100\n" +"PO-Revision-Date: 2016-01-20 14:19:50.044602\n" +"Last-Translator: h404bi\n" +"Language-Team: h404bi\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. The name of the warning timer displaying the time left before the next +#. border +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:84 +msgid "Border shrinking" +msgstr "地图缩小倒计时" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:363 +msgid "{cs}All players are inside the given border." +msgstr "{cs}所有玩家均在边界内." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:367 +msgid "{ci}There are {0} players outside the given border." +msgstr "{ci}有 {0} 位玩家在边界外." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:373 +msgid "{lightpurple} - {red}{0}{ci} (far away from the border)" +msgstr "{lightpurple} - {red}{0}{ci} (远离边界)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:377 +msgid "{lightpurple} - {yellow}{0}{ci} (close to the border)" +msgstr "{lightpurple} - {yellow}{0}{ci} (靠近边界)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:381 +msgid "{lightpurple} - {green}{0}{ci} (very close to the border)" +msgstr "{lightpurple} - {green}{0}{ci} (非常靠近边界)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{red}Warning!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:423 +msgid "{white}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:425 +msgid "{red}{bold}The border begins to shrink..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/borders/BorderManager.java:426 +msgid "" +"{gray}It will shrink by one block every {0} second(s) until {1} blocks in " +"diameter." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:42 +msgctxt "protip" +msgid "" +"{gray}You can lock and unlock the team chat with {cc}/togglechat{gray}." +msgstr "{gray}可以使用 {cc}/togglechat{gray} 指令打开或关闭队伍聊天." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:43 +msgctxt "protip" +msgid "{gray}You can send a global message using {cc}/g <message>{gray}." +msgstr "{gray}可以使用 {cc}/g <message>{gray} 指令发送世界消息." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:44 +msgctxt "protip" +msgid "{gray}You can send a team-chat message with {cc}/t <message>{gray}." +msgstr "{gray}可以使用 {cc}/t <message>{gray} 指令发送队伍消息." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:46 +msgctxt "protip" +msgid "" +"{gray}You can craft golden apples with heads (same recipe with a head " +"instead of an apple)." +msgstr "{gray}可以使用掉落的头颅制作金苹果(配方相同, 但将苹果换成头颅)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:47 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder." +msgstr "{gray}指南针的合成配方还需要在四个角落加上骨头, 腐肉, 蜘蛛眼和火药." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:48 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an ender pearl." +msgstr "{gray}指南针的合成配方还需要在四个角落加上骨头, 腐肉, 蜘蛛眼和火药, 并将中间的红石换成末影珍珠." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:49 +msgctxt "protip" +msgid "" +"{gray}The compass is crafted with, in the corners, a bone, a rotten flesh, a" +" spider eye and a gunpowder; in the center, an Eye of Ender." +msgstr "{gray}指南针的合成配方还需要在四个角落加上骨头, 腐肉, 蜘蛛眼和火药, 并将中间的红石换成末影之眼." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:50 +msgctxt "protip" +msgid "{gray}The glistering melon is crafted with a melon and a gold block." +msgstr "{gray}闪烁的西瓜需要用西瓜和金块合成." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:52 +msgctxt "protip" +msgid "{gray}The enchanted golden apple is disabled for this game." +msgstr "{gray}附魔金苹果已被禁止合成." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTips.java:54 +msgctxt "protip" +msgid "" +"{gray}Fallen on a tree? Jump, you have a few seconds left to remain " +"invincible." +msgstr "{gray}掉到树上了? 快跳吧, 你有25秒的无敌时间." + +#. ProTip invite, displayed before a ProTip. +#: src/main/java/eu/carrade/amaury/UHCReloaded/protips/ProTip.java:131 +msgid "{darkpurple}ProTip!" +msgstr "{darkpurple}小贴士!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/UHCReloaded.java:204 +msgid "Ultra Hardcore plugin loaded." +msgstr "UHC插件已加载" + +#. The title of the delete team GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:61 +msgid "{0} » {darkred}Delete" +msgstr "" + +#. The title of the "keep" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:69 +msgid "{green}Keep this team alive" +msgstr "" + +#. The title of the "delete" button in the delete team GUI +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditDeleteGUI.java:81 +msgid "{red}Delete this team {italic}forever" +msgstr "" + +#. The title of the edit team members GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:68 +msgid "{0} » {black}Members" +msgstr "" + +#. Go back button in GUIs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:77 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:123 +msgid "{green}« Go back" +msgstr "" + +#. The title of a button to select a player (a skull button). {0} = player's +#. display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:135 +msgid "{reset}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Online" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:137 +msgid "{gray}Offline" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: {0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:138 +msgid "{gray}Current team: none" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to add this player" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditMembersGUI.java:99 +msgid "{darkgray}» {white}Click {gray}to remove this player" +msgstr "" + +#. The title of the edit team color GUI. {0} = team name (raw). +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditColorGUI.java:54 +msgid "{0} » {black}Color" +msgstr "" + +#. The title of the edit team GUI. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:67 +msgid "Teams » {black}{0}" +msgstr "" + +#. Members count in the banner description, in the team edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:73 +msgid "{white}{0} {gray}member" +msgid_plural "{white}{0} {gray}members" +msgstr[0] "" + +#. Update team color button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:81 +msgid "{green}Update the color" +msgstr "" + +#. Current team color in edit GUI. {0} = formatted color name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:83 +msgctxt "current_team_color" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Rename team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:90 +msgid "{green}Rename the team" +msgstr "" + +#. Current team name in edit GUI. {0} = raw team name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:92 +msgctxt "current_team_name" +msgid "{gray}Current: {white}{0}" +msgstr "" + +#. Online status dot in /uh infos +#. Online dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:149 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:83 +msgid "{green} • " +msgstr "{green} • " + +#. Offline status dot in /uh infos +#. Offline dot in /uh team list +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:98 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:153 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:88 +msgid "{red} • " +msgstr "{red} • " + +#. Update team members button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:106 +msgid "{green}Add or remove players" +msgstr "" + +#. Delete team button in edit GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:114 +msgid "{red}Delete this team" +msgstr "" + +#. Warning under the "delete team" button title. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/editor/TeamEditGUI.java:116 +msgid "{gray}Cannot be undone" +msgstr "" + +#. The title of the teams selector GUI. {0} = teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:77 +msgid "{black}Select a team {reset}({0})" +msgstr "" + +#. The title of a button to rename our team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:89 +msgid "{white}Rename your team" +msgstr "" + +#. Warning displayed in the "Rename your team" button, if the player is not in +#. a team +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:91 +msgid "{gray}You have to be in a team" +msgstr "" + +#. The title of a button to create a new team, in the selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:100 +msgid "{white}New team" +msgstr "" + +#. The "Players" title in the selector GUI, on a team's tooltip +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:118 +msgid "{blue}Players" +msgstr "" + +#. An item of the players list in the selector GUI, on a team's tooltip +#. A member bullet in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:118 +msgid "{darkgray}- {white}{0}" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:130 +msgid "{darkgray}» {white}Click {gray}to join this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:134 +msgid "{darkgray}» {white}Click {gray}to leave this team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:139 +msgid "{darkgray}» {white}Right-click {gray}to manage this team" +msgstr "" + +#. Title of the team item in the teams selector GUI (with max). {0}: team +#. display name. {1}: players count. {2}: max count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:177 +msgid "{white}Team {0} {gray}({1}/{2})" +msgstr "" + +#. Title of the team item in the teams selector GUI (without max) {0}: team +#. display name. {1}: players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/TeamsSelectorGUI.java:179 +msgid "{white}Team {0} {gray}({1} player)" +msgid_plural "{white}Team {0} {gray}({1} players)" +msgstr[0] "" + +#. The title of the first step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:109 +msgid "{gray}1. {white}{bold}Team color" +msgstr "" + +#. The title of the second step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:111 +msgid "{gray}2. {white}{bold}Team name" +msgstr "" + +#. The title of the third step in the team creator GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderBaseGUI.java:113 +msgid "{gray}3. {white}{bold}Team members" +msgstr "" + +#. The title of the name selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:57 +msgid "New team » {black}Name" +msgstr "" + +#. The title of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:65 +msgid "{white}Name the team" +msgstr "" + +#. The legend of the button opening the sign to write the team name (creator +#. GUIs) +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepNameGUI.java:67 +msgid "" +"{gray}When clicked, a sign will open; write the name of the team inside." +msgstr "" + +#. The title of the color selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:61 +msgid "New team » {black}Color" +msgstr "" + +#. The random color button in a colors selector GUI. +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepColorGUI.java:74 +msgid "{lightpurple}Random color" +msgstr "" + +#. The title of the members selector GUI, in the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:80 +msgid "New team » {black}Members" +msgstr "" + +#. The summary title in the final « create the team » button of the create +#. team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:106 +msgid "{blue}{bold}Summary" +msgstr "" + +#. The team name in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:108 +msgid "{gray}Team name: {white}{0}" +msgstr "" + +#. The team color in the final « create the team » button of the create team +#. GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:110 +msgid "{gray}Color: {0}" +msgstr "" + +#. The team members count in the final « create the team » button of the +#. create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:112 +msgid "{gray}Members: {white}{0}" +msgstr "" + +#. The title of the final « create the team » button of the create team GUIs +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:122 +msgid "{green}Create the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{lightpurple}Selected!" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:140 +msgid "{darkgray}» {white}Click {gray}to add to the team" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:173 +msgid "{cs}Team created." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/gui/teams/builder/TeamBuilderStepPlayersGUI.java:177 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:118 +msgid "{ce}This team already exists." +msgstr "{ce}队伍已存在." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:208 +#, java-format +msgid "Spawn point {0},{1} added from the config file" +msgstr "预设出生点 {0},{1} 已从配置文件载入" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/spawns/SpawnsManager.java:213 +#, java-format +msgid "Invalid spawn point set in config: {0}" +msgstr "配置文件预设的出生点无效: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:141 +msgid "{cs}Your team is now called {0}{cs}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:302 +msgid "{aqua}You are now in the {0}{aqua} team." +msgstr "{aqua}你已加入到队伍 {0}{aqua} 中." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:335 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/UHTeam.java:369 +msgid "{darkaqua}You are no longer part of the {0}{darkaqua} team." +msgstr "{darkaqua}你不再是队伍 {0}{darkaqua} 的队员." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:84 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:211 +msgid "{ce}You are not allowed to send a private message to your team." +msgstr "{ce}你不能发送队伍消息." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:216 +msgid "{ce}You are not allowed to enter in the private chat of another team." +msgstr "{ce}你不能向其他队伍发送消息." + +#. Format of a private team message from a team member. {0} = sender display +#. name, {1} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:99 +msgid "{gold}[{0}{gold} -> his team] {reset}{1}" +msgstr "{gold}[{0}{gold} -> 队伍聊天] {reset}{1}" + +#. Error message if someone try to send a team private message out of any team +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:105 +msgid "{ce}You are not in a team!" +msgstr "{ce}你尚未加入任何队伍!" + +#. Format of a private team message from a non-team-member. {0} = sender +#. display name, {1} = team display name, {2} = message. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamChatManager.java:112 +msgid "{gold}[{0}{gold} -> team {1}{gold}] {reset}{2}" +msgstr "{gold}[{0}{gold} -> 队伍 {1}{gold}] {reset}{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:443 +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:461 +#, java-format +msgid "Invalid team set in config: {0}" +msgstr "配置文件预设的队伍无效: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:450 +#, java-format +msgid "Team {0} ({1}) added from the config file" +msgstr "预设队伍 {0} ({1}) 已从配置文件加入" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:456 +#, java-format +msgid "Team {0} added from the config file" +msgstr "预设队伍 {0} 已从配置文件载入" + +#. Invite displayed in the chat team selector +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:497 +msgid "{gold}Click on the names below to join a team" +msgstr "{gold}加入队伍请点击队伍名字" + +#. Team count with max players (ex. [3/5]) followed in-game by the team name. +#. {0} = current count, {1} = max. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:511 +msgid "{gray}[{white}{0}{gray}/{white}{1}{gray}]" +msgstr "{gray}[{white}{0}{gray}/{white}{1}{gray}]" + +#. Team count without max players (ex. [3]) followed in-game by the team name. +#. {0} = current count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:516 +msgid "{gray}[{white}{0}{gray}]" +msgstr "{gray}[{white}{0}{gray}]" + +#. Displayed in team tooltip of the chat team selector for a dead player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:534 +msgid "{0} ({red}dead{reset})" +msgstr "" + +#. Displayed in team tooltip of the chat team selector for an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:539 +msgid "{0} ({green}alive{reset})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:544 +#, java-format +msgid "{0} player in this team" +msgid_plural "{0} players in this team" +msgstr[0] "{0} 位玩家" + +#. Tooltip on the chat team selector GUI when the player is in the team. {0} = +#. team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:557 +#, java-format +msgid "You are in the team {0}" +msgstr "你已加入到队伍 {0} 中." + +#. Tooltip on the chat team selector GUI when the player is not in the team. +#. {0} = team display name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:562 +#, java-format +msgid "Click here to join the team {0}" +msgstr "点击加入队伍 {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:574 +msgid "{darkred}[×] {red}Click here to leave your team" +msgstr "{darkred}[×] {red}点击离开当前队伍" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:582 +msgid "{gray}Run /join to display this again" +msgstr "{gray}输入 /join 再次显示本菜单" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/teams/TeamManager.java:588 +msgid "{ce}There isn't any team available." +msgstr "{ce}没有队伍" + +#. The kick message of a player when death.kick.do = true in config +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:162 +msgid "jayjay" +msgstr "啊呀呀呀" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:240 +#, java-format +msgid "{0}The team {1} has fallen!" +msgstr "{0}队伍 {1} 已团灭!" + +#. A message displayed to the players under the death screen, about the +#. respawn possibility even if the death screen says the opposite (in hardcore +#. mode) +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:284 +msgid "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} YOU CAN " +"RESPAWN{lightpurple}, just click {italic}Respawn {lightpurple}on the next " +"screen." +msgstr "" +"{darkpurple}{obfuscated}----{lightpurple}{italic} 你可以复活{lightpurple}, " +"只需点击{italic}屏幕上的{lightpurple}复活按钮." + +#. The kick message displayed if a player tries to relog after his death and +#. it's forbidden by the config. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:442 +msgid "You are dead!" +msgstr "你已死亡!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:515 +msgid "{darkred}[UHC] {ce}WorldBorder is not installed: no borders' check!" +msgstr "{darkred}[UHC] {ce}WorldBorder插件未安装: 将不进行边界检查" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:516 +msgid "" +"{gray}Also, without WorldBorder, the border can't be reduced during the game" +" (warnings excluded)." +msgstr "{gray}WorldBorder插件未安装, 将不能缩小边界(越界警告仍可设置)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:517 +msgid "" +"{gray}Just install the plugin; UHPlugin will automatically configure it." +msgstr "{gray}请安装WorldBorder插件, UHPlugin插件会自动进行配置" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:527 +msgid "{darkred}[UHC] {ce}ProtocolLib is needed but not installed!" +msgstr "{darkred}[UHC] {ce}前置插件ProtocolLib未安装" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:528 +msgid "{gray}The following options require the presence of ProtocolLib:" +msgstr "{gray}以下设置需要ProtocolLib插件的支持: " + +#. An option requiring ProtocolLib, in the “missing PLib” message. {0} = +#. option path. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:532 +msgctxt "protocollib_option" +msgid "{darkgray} - {gray}{0}" +msgstr "{darkgray} - {gray}{0}" + +#. {0} = ProtocolLib download URL for the current Minecraft version. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:545 +msgid "{gray}ProtocolLib is available here: {0}" +msgstr "{gray}可以从这里获取ProtocolLib插件: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:673 +msgid "{cs}The timer before the new border is up!" +msgstr "{cs}时间到, 地图即将缩小!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:705 +msgid "{aqua}-------- End of episode {0} [forced by {1}] --------" +msgstr "{aqua}-------- 阶段 {0} 已结束 [由 {1} 强制结束] --------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:709 +msgid "{aqua}-------- End of episode {0} --------" +msgstr "{aqua}-------- 阶段 {0} 已结束 --------" + +#. The title displayed when the episode change. {0} = new episode number; {1} +#. = old. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:721 +msgid "{darkaqua}Episode {aqua}{0}" +msgstr "" + +#. Start message broadcasted in chat +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:745 +msgid "{green}--- GO ---" +msgstr "{green}--- 走起! ---" + +#. Title of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:753 +msgid "{darkgreen}Let's go!" +msgstr "" + +#. Subtitle of title displayed when the game starts. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:755 +msgid "{green}Good luck, and have fun" +msgstr "" + +#. Resurrection notification. {0} = raw resurrected player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameListener.java:887 +msgid "{gold}{0} returned from the dead!" +msgstr "{gold}玩家 {0} 复活了!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:200 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:279 +msgid "{aqua}Golden head" +msgstr "{aqua}金苹果(金头颅)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:201 +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/CraftingListener.java:280 +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}金苹果(金头颅)" + +#. Error message if a player tries to use his pointing compass without rotten +#. flesh. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:304 +msgid "{gray}{italic}You do not have rotten flesh." +msgstr "{gray}{italic}你没有腐肉." + +#. Error message if a player tries to use his pointing compass without a +#. player nearby. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:335 +msgid "{gray}{italic}Only silence answers your request." +msgstr "{gray}{italic}指南针没找到任何特殊事物." + +#. Success message when a player uses his pointing compass. +#: src/main/java/eu/carrade/amaury/UHCReloaded/listeners/GameplayListener.java:342 +msgid "{gray}The compass now points to the closest player." +msgstr "{gray}指南针正指向离你最近的玩家." + +#. Dynmap marker label of a death point +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:152 +#, java-format +msgid "Death point of {0}" +msgstr "{0} 的死亡地点" + +#. Dynmap marker label of a spawn point of a team. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:231 +#, java-format +msgid "Spawn point of the team {0}" +msgstr "队伍 {0} 的出生点" + +#. Dynmap marker label of a spawn point of a player, in solo. +#. Dynmap marker label of a spawn point of a player, when the teleportation +#. ignores the teams. +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:236 +#: src/main/java/eu/carrade/amaury/UHCReloaded/integration/UHDynmapIntegration.java:293 +#, java-format +msgid "Spawn point of {0}" +msgstr "{0} 的出生点" + +#. Golden head lore for withers +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:285 +msgid "Made from the fallen head of a malignant monster" +msgstr "用怪物掉落的头颅制作" + +#. Golden head lore for players. {0} = player name. +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:290 +#, java-format +msgid "Made from the fallen head of {0}" +msgstr "用玩家 {0} 掉落的头颅制作" + +#. Item name of a golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:393 +msgctxt "player_head" +msgid "{aqua}Golden head" +msgstr "{aqua}金苹果(金头颅)" + +#. Item name of an enchanted golden head (from a player) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:399 +msgctxt "player_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}金苹果(金头颅)" + +#. Item name of a golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:426 +msgctxt "monster_head" +msgid "{aqua}Golden head" +msgstr "{aqua}金苹果(金头颅)" + +#. Item name of an enchanted golden head (from a monster) +#: src/main/java/eu/carrade/amaury/UHCReloaded/recipes/RecipesManager.java:432 +msgctxt "monster_head" +msgid "{lightpurple}Golden head" +msgstr "{lightpurple}金苹果(金头颅)" + +#. Current episode in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:141 +msgid "{gray}Episode {white}{0}" +msgstr "{gray}阶段 {white}{0}" + +#. Players alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:150 +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:159 +msgid "{white}{0}{gray} player" +msgid_plural "{white}{0}{gray} players" +msgstr[0] "{white}{0}{gray} 位玩家" + +#. Teams alive in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:163 +msgid "{white}{0}{gray} team" +msgid_plural "{white}{0}{gray} teams" +msgstr[0] "{white}{0}{gray} 个队伍" + +#. Title of the team section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:205 +msgid "{bold}Your team" +msgstr "" + +#. Kills count in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:278 +msgid "{white}{0}{gray} player killed" +msgid_plural "{white}{0}{gray} players killed" +msgstr[0] "" + +#. Title of the border section in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:309 +msgid "{blue}{bold}Border" +msgstr "" + +#. Border diameter for a squared map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:317 +msgid "{white}{0} block wide" +msgid_plural "{white}{0} blocks wide" +msgstr[0] "" + +#. Border diameter for a circular map in the sidebar +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:320 +msgid "{gray}Diameter: {white}{0} block" +msgid_plural "{gray}Diameter: {white}{0} blocks" +msgstr[0] "" + +#. Min & max coordinates in the sidebar, to locate the border. Ex: "-500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:336 +msgid "{white}{0} {1}" +msgstr "" + +#. Min & max X coordinates in the sidebar, to locate the border. Ex: "X: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:341 +msgid "{gray}X: {white}{0} {1}" +msgstr "" + +#. Min & max Z coordinates in the sidebar, to locate the border. Ex: "Z: -500 +#. +500". {0} = minimal coord, {1} = maximal coord. +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:343 +msgid "{gray}Z: {white}{0} {1}" +msgstr "" + +#. Notice displayed at the bottom of the sidebar if the game is paused (/uh +#. freeze all). +#: src/main/java/eu/carrade/amaury/UHCReloaded/scoreboard/GameSidebar.java:384 +msgid "{darkaqua}Game frozen" +msgstr "{darkaqua}游戏已冻结" + +#. Title of the rules box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:121 +msgid "{red}{bold}Rules and informations" +msgstr "" + +#. Rule item in the rule box. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/RulesManager.java:132 +msgid "{darkgray}- {reset}{0}" +msgstr "" + +#. Episode in the player list ({episodeText} replacement). {0} = current +#. episode number. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:117 +#, java-format +msgid "Episode {0}" +msgstr "阶段 {0}" + +#. Players in the player list ({playersText} replacement). {0} = current alive +#. players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:119 +#, java-format +msgid "{0} player" +msgid_plural "{0} players" +msgstr[0] "{0} 位玩家" + +#. Teams in the player list ({teamsText} replacement). {0} = current alive +#. teams count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/PlayerListHeaderFooterManager.java:121 +#, java-format +msgid "{0} team" +msgid_plural "{0} teams" +msgstr[0] "{0} 个队伍" + +#. MOTD when the game is not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:89 +msgid "Waiting for players..." +msgstr "等待玩家中..." + +#. MOTD when the game is starting (slow TP in progress). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:98 +msgid "Starting in progress..." +msgstr "游戏开始中..." + +#. Solo game running MOTD. {0} = players alive count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:113 +#, java-format +msgid "Game running! {0} player alive." +msgid_plural "Game running! {0} players alive." +msgstr[0] "游戏开始! 共 {0} 位玩家. " + +#. Teams game running MOTD. {0} = players alive count. {1} = teams alive +#. count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:118 +#, java-format +msgid "Game running! {0} player alive in {1} team." +msgid_plural "Game running! {0} players alive in {1} teams." +msgstr[0] "游戏开始! 共 {0} 位玩家, {1} 个队伍." + +#. Game finished MOTD with solo winner ({0} = winner raw name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:135 +#, java-format +msgid "Game finished; congratulation to {0} for his victory!" +msgstr "游戏结束; 祝贺 {0} 赢得胜利!" + +#. Game finished MOTD with team winner ({0} = team display name). +#: src/main/java/eu/carrade/amaury/UHCReloaded/misc/MOTDManager.java:140 +#, java-format +msgid "Game finished; the team {0} wins this match!" +msgstr "游戏结束; 祝贺队伍 {0} 赢得胜利!" + +#. Timer. {0} = hours; {1} = minutes; {2} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:404 +msgid "{0}{gray}:{white}{1}{gray}:{white}{2}" +msgstr "{0}{gray}:{white}{1}{gray}:{white}{2}" + +#. Timer. {0} = minutes; {1} = seconds. +#: src/main/java/eu/carrade/amaury/UHCReloaded/timers/UHTimer.java:409 +msgid "{white}{0}{gray}:{white}{1}" +msgstr "{white}{0}{gray}:{white}{1}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:39 +msgid "{aqua}------ Game-related commands ------" +msgstr "{aqua}------ 游戏相关指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:40 +msgid "{aqua}------ Bugs-related commands ------" +msgstr "{aqua}------ 管理相关指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/categories/Category.java:41 +msgid "{aqua}------ Miscellaneous commands ------" +msgstr "{aqua}------ 杂项指令 ------" + +#. Usage of the /g and /t commands +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/GlobalMessageCommand.java:109 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/TeamMessageCommand.java:107 +msgid "{ce}Usage: /{0} <message>" +msgstr "{ce}用法: /{0} <message>" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:94 +msgid "{aqua}------ Spawns points commands ------" +msgstr "{aqua}------ 出生点指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpawnsCommand.java:100 +msgid "" +"{cc}/uh spawns {ci}: manages the spawn points. Execute /uh spawns for " +"details." +msgstr "{cc}/uh spawns {ci}: 出生点管理. 输入 /uh spawns 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:144 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:188 +msgid "{ce}The coordinates must be three valid numbers." +msgstr "{ce}坐标必须是三个有效数字." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:148 +msgid "{ce}This team is not registered." +msgstr "{ce}队伍不存在." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:157 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:199 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:109 +msgid "{ce}{0} is offline!" +msgstr "{ce}{0} 当前离线!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:263 +msgid "{aqua}------ Teleportation commands ------" +msgstr "{aqua}------ 传送指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:264 +msgid "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: teleports the team " +"to the given location/target." +msgstr "" +"{cc}/uh tp team <x> <y> <z> | <target> <team ...> {ci}: 将队伍传送到指定的目标或地点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:265 +msgid "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: teleports the spectators " +"(aka non-alive players) to the given location/target." +msgstr "" +"{cc}/uh tp spectators <x> <y> <z> | <target> {ci}: 将旁观者(即已死亡玩家)传送到指定的目标或地点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPCommand.java:272 +msgid "" +"{cc}/uh tp {ci}: teleports the spectators or an entire team. See /uh tp for " +"details." +msgstr "{cc}/uh tp {ci}: 传送旁观者或者整个队伍. 输入 /uh tp 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:208 +msgid "{yellow}{0} - version {1}" +msgstr "{yellow}{0} - 版本号: {1}" + +#. The "and" in the authors list (like "Amaury Carrade, azenet and João Roda") +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:94 +msgctxt "authors_list" +msgid "and" +msgstr "和" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:102 +#, java-format +msgid "Plugin made with love by {0}." +msgstr "本插件由 {0} 用心制作" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:129 +#, java-format +msgid "Build number: {0}." +msgstr "构建版本号: {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:133 +msgid "Build number not available." +msgstr "构建版本号不可用" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:138 +msgid "{aqua}------ Translations ------" +msgstr "{aqua}------ 翻译 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:139 +#, java-format +msgid "Current language: {0} (translated by {1})." +msgstr "当前语言: {0} (由 {1} 翻译)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:140 +#, java-format +msgid "Fallback language: {0} (translated by {1})." +msgstr "备用语言: {0} (由 {1} 翻译)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:141 +msgid "{aqua}------ License ------" +msgstr "{aqua}------ 许可 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:142 +msgid "Published under the CeCILL-B License." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHAboutCommand.java:170 +msgid "{cc}/uh about {ci}: informations about the plugin and the translation." +msgstr "{cc}/uh about {ci}: 本插件及其翻译相关信息" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:67 +msgid "{cs}Warning canceled." +msgstr "{cs}警告已取消." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:82 +msgid "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} second." +msgid_plural "" +"{cs}Future size saved. All players outside this future border will be warned " +"every {0} seconds." +msgstr[0] "{cs}地图新大小已保存. 所有在地图新边界外的玩家每隔 {0} 秒将收到越界警告." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:99 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:124 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:71 +msgid "{ce}“{0}” is not a number..." +msgstr "{ce}“{0}” 不是数字..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: warns " +"all players outside the given future diameter. It's just a notice, nothing " +"else." +msgstr "" +"{cc}/uh border warning <futureDiameter> [minutesBeforeReduction]{ci}: " +"提示所有超出了地图新直径的玩家. 仅提示, 不作变更" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderWarningCommand.java:112 +msgid "{cc}/uh border warning cancel{ci}: cancels a previously-set warning." +msgstr "{cc}/uh border warning cancel{ci}: 取消已设置的警告提示" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:74 +msgid "" +"{ce}Some players are outside the future border, so this operation was " +"cancelled." +msgstr "{ce}有玩家在边界外, 操作已取消." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:75 +msgid "" +"{ci}Use {cc}/uh border set {0} force{ci} to resize the border regardless to " +"this point." +msgstr "{ci}使用 {cc}/uh border set {0} force{ci} 来强制改变边界." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:78 +msgid "" +"{ce}WARNING: {ci}because WorldBorder is not installed, players out of the " +"border will not be teleported!" +msgstr "{ce}警告: {ci}WorldBorder插件未安装, 边界外的玩家将不能被传送到边界内!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:114 +msgid "{lightpurple}The diameter of the map is now {0} block." +msgid_plural "{lightpurple}The diameter of the map is now {0} blocks." +msgstr[0] "{lightpurple}当前地图直径为 {0} 个方块." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:118 +msgid "{lightpurple}The size of the map is now {0}×{0}." +msgstr "{lightpurple}当前地图大小为 {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderSetCommand.java:149 +msgid "" +"{cc}/uh border set <diameter> [force]{ci}: changes the size of the map. If " +"force is not given, the operation will be canceled if there is a player " +"outside the border." +msgstr "" +"{cc}/uh border set <diameter> [force]{ci}: 更改地图大小. 若 force 参数未指定且有玩家在变更的边界外," +" 则指令不会生效" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderCheckCommand.java:91 +msgid "" +"{cc}/uh border check <diameter>{ci}: returns a list of the players outside " +"the given border size." +msgstr "{cc}/uh border check <diameter>{ci}: 列出所有在指定的边界外的玩家" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:60 +msgid "{ci}The current diameter of the map is {0} block." +msgid_plural "{ci}The current diameter of the map is {0} blocks." +msgstr[0] "{ci}当前地图直径为 {0} 个方块." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:64 +msgid "{ci}The current map size is {0}×{0}." +msgstr "{ci}当前地图大小为 {0}*{0}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/border/UHBorderGetCommand.java:83 +msgid "{cc}/uh border get{ci}: returns the current size of the map." +msgstr "{cc}/uh border get{ci}: 显示当前地图大小" + +#. Header of the /uh infos command. Plural based on the players count. +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:69 +msgid "{ci}{0} player alive in {1} team." +msgid_plural "{ci}{0} players alive in {1} teams." +msgstr[0] "{ci}{0} 位玩家, {1} 个队伍." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:73 +msgid "{ci}The game is not started." +msgstr "{ci}游戏尚未开始." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:93 +msgid "Currently online" +msgstr "当前在线" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:99 +msgid "Currently offline" +msgstr "当前离线" + +#. Team name in tooltip in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:108 +#, java-format +msgid "Team: {0}" +msgstr "队伍: {0}" + +#. Separator in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:115 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:160 +msgid "{gray} - " +msgstr "{gray} - " + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:164 +msgid "{green}alive" +msgstr "{green}存活" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:125 +#, java-format +msgid "{0} half-hearts" +msgstr "{0} 点生命值" + +#. Alive state in /uh infos +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:131 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:168 +msgid "{red}dead" +msgstr "{red}死亡" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHInfosCommand.java:196 +msgid "{cc}/uh infos {ci}: prints some infos about the current game." +msgstr "{cc}/uh infos {ci}: 输出关于本场游戏的一些信息" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:75 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:88 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:87 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:100 +msgid "" +"{ce}Food points and saturation must be numbers (floats for the saturation)!" +msgstr "{ce}饥饿值和饱食度必须是数字 (饱食度可以带小数点)!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedAllCommand.java:116 +msgid "" +"{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: feeds all players." +msgstr "{cc}/uh feedall [foodPoints=20] [saturation=max] {ci}: 给所有玩家增加饥饿值和饱食度" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:97 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:118 +msgid "{cs}Spawn added in the world {0}: {1};{2}" +msgstr "{cs}出生点已添加 {0}: {1};{2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:101 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:126 +msgid "{ce}You cannot add a spawn point out of the borders." +msgstr "{ce}不能在边界外生成出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:105 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:130 +msgid "{ce}Unable to add this spawn point: no safe spot found in the Nether." +msgstr "{ce}无法生成该出生点: 无法在下界找到安全的出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:85 +msgid "{ce}You need to specify two coordinates." +msgstr "{ce}你必须指定两个坐标值." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:122 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:186 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:106 +msgid "{ce}This is not a number!" +msgstr "{ce}参数非数字!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsAddCommand.java:152 +msgid "" +"{cc}/uh spawns add {ci}: adds a spawn point for a team or a player, at the " +"current location of the sender or at the provided coordinates." +msgstr "{cc}/uh spawns add {ci}: 增加一个出生点, 指定坐标或使用指令发送者当前所在坐标" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:119 +msgid "{ci}No team found: assuming the game is a solo game." +msgstr "{ci}未发现队伍: 若继续则每位玩家将各自为战." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:136 +msgid "" +"{ci}Some players are not in a team; their number was added to the spawn " +"count." +msgstr "{ci}有玩家尚未加入队伍, 将各自独立成队参与游戏并占用等量的出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:174 +msgid "{ce}The world {0} doesn't exists." +msgstr "{ce}世界 {0} 不存在." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:193 +msgid "{ci}You asked for a void generation. Thus, the generation is empty." +msgstr "{ci}请求生成的出生点为空." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:205 +msgid "{ce}The generation method “{0}” is not (yet?) supported." +msgstr "{ce}暂不支持 “{0}” 生成方法." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:211 +msgid "" +"{ce}You asked for the impossible: there are too many spawn points on a too " +"small surface. Decrease the spawn count or the minimal distance between two " +"points." +msgstr "{ce}出生点生成失败: 地图太小, 出生点太多. 请减少出生点数目或缩小出生点之间的间距." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:215 +msgid "{cs}Successfully generated the asked spawn points." +msgstr "{cs}出生点已生成." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:277 +msgid "{aqua}Command" +msgstr "{aqua}指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:278 +msgid "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" +msgstr "" +"{cc}/uh spawns generate <circular|grid|random> [size] [distanceMin] [count] " +"[xCenter] [zCenter] [world]" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:279 +msgid "{aqua}Shapes" +msgstr "{aqua}形状" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:280 +msgid "" +" - {cc}random{ci}: generates random spawn points on the map, with a minimal " +"distance between them." +msgstr " - {cc}random{ci}: 在地图上随机生成出生点. 出生点之间使用最小距离(distanceMin参数)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:281 +msgid "" +" - {cc}grid{ci}: generates the spawn points on concentric squares, with a " +"constant distance between two generated points." +msgstr " - {cc}grid{ci}: 在同心正方形上生成出生点. 两出生点之间使用固定距离" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:282 +msgid "" +" - {cc}circular{ci}: generates the spawn points on concentric circles, with " +"a minimal distance between two generated points. In each circle, the angle " +"(and the distance) between two spawn points is constant." +msgstr "" +" - {cc}circular{ci}: 在同心圆上生成出生点, 两出生点之间使用最小距离. 每个圆上, 两出生点之间的角度及距离都是固定的" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:283 +msgid "{aqua}Arguments" +msgstr "{aqua}参数" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:284 +msgid "" +" - {cc}size{ci}: the size of the region where the spawn points will be " +"generated. Squared or circular, following the shape of the map. Default: " +"map' size." +msgstr " - {cc}size{ci}: 设定生成出生点区域的大小. 根据地图的形状使用正方形或者圆形. 默认值: 地图大小" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:285 +msgid "" +" - {cc}distanceMin{ci}: the minimal distance between two spawn points. " +"Default: 250 blocks." +msgstr " - {cc}distanceMin{ci}: 两出生点之间的最小距离. 默认值: 250个方块" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:286 +msgid "" +" - {cc}count{ci}: the number of spawn points to generate. Default: the " +"number of players or teams." +msgstr " - {cc}count{ci}: 生成出生点的个数. 默认值: 玩家数或队伍数" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:287 +msgid "" +" - {cc}xCenter{ci}, {cc}zCenter{ci}: the center of the region where the " +"points are generated. Default: world' spawn point." +msgstr " - {cc}xCenter{ci}, {cc}zCenter{ci}: 设定生成出生点区域的中心点. 默认值: 世界出生点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:288 +msgid " - {cc}world{ci}: the world where the spawn points will be generated." +msgstr " - {cc}world{ci}: 在哪个世界生成出生点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsGenerateCommand.java:295 +msgid "" +"{cc}/uh spawns generate {ci}: automagically generates spawn points. See /uh " +"spawns generate for details." +msgstr "{cc}/uh spawns generate {ci}: 自动生成出生点. 输入 /uh spawns generate 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsDumpCommand.java:126 +msgid "" +"{cc}/uh spawns dump {ci}: displays the registered spawn points in an " +"exportable format. {gray}Use this to plot the spawn points, as example." +msgstr "{cc}/uh spawns dump {ci}: 以导出格式列出所有已生成的出生点. {gray}比如用来绘制出生点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:75 +msgid "{ce}There isn't any registered spawn point." +msgstr "{ce}尚无出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:79 +msgid "{ci}There are {0} registered spawn points." +msgstr "{ci}共 {0} 个出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:100 +msgid "{lightpurple}World {0}" +msgstr "{lightpurple}世界 {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsListCommand.java:180 +msgid "{cc}/uh spawns list {ci}: lists the registered spawn points." +msgstr "{cc}/uh spawns list {ci}: 列出所有已生成的出生点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:67 +msgid "{cs}All the spawn points were removed." +msgstr "{cs}已删除所有出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsResetCommand.java:93 +msgid "{cc}/uh spawns reset {ci}: removes all registered spawn points." +msgstr "{cc}/uh spawns reset {ci}: 删除所有已生成的出生点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:80 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:102 +msgid "{cs}The spawn point {1};{2} in the world {0} was removed." +msgstr "{cs}世界 {0} 的出生点 {1};{2} 已删除." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/spawns/UHSpawnsRemoveCommand.java:134 +msgid "" +"{cc}/uh spawns remove [<x> <z>] {ci}: removes the spawn points at the " +"specified coordinates, or at the current location if the sender without " +"coordinates." +msgstr "" +"{cc}/uh spawns remove [<x> <z>] {ci}: 删除在指定坐标上的出生点. 若未指定坐标则为指令发送者当前所在坐标" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:70 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:89 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:110 +msgid "{ce}The player {0} is not online." +msgstr "{ce}玩家 {0} 当前离线." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:75 +msgid "{ce}No death location available for the player {0}." +msgstr "{ce}没有玩家 {0} 有效的死亡地点信息." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:85 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:90 +msgid "{cs}The player {0} was teleported back." +msgstr "{cs}已传送玩家 {0} 回其死亡地点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:95 +msgid "" +"{ce}The player {0} was NOT teleported back because no safe spot was found." +msgstr "{ce}传送点不安全, 传送玩家 {0} 失败." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:96 +msgid "" +"{ci}Use {cc}/uh tpback {0} force{ci} to teleport the player regardless this " +"point." +msgstr "{ci}使用 {cc}/uh tpback {0} force{ci} 来强制传送玩家." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPBackCommand.java:135 +msgid "" +"{cc}/uh tpback <player> [force] {ci}: safely teleports back a player to his " +"death location." +msgstr "{cc}/uh tpback <player> [force] {ci}: 将玩家安全地传送到其死亡地点" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:76 +msgid "{ce}The game is not started!" +msgstr "{ce}游戏尚未开始!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:80 +msgid "{ce}There's not one team alive!" +msgstr "{ce}没有存活的队伍!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFinishCommand.java:104 +msgid "" +"{cc}/uh finish {ci}: displays the name of the winner(s) and launches some " +"fireworks." +msgstr "{cc}/uh finish {ci}: 显示获胜者并燃放焰火祝贺" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:66 +msgid "" +"{ce}The spawn points are not already assigned to the player, because the " +"game is not started." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:87 +msgid "{ce}No spawn location available for the player {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:95 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:99 +msgid "{cs}The player {0} was teleported to his spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:103 +msgid "" +"{ce}The player {0} was NOT teleported to his spawn because no safe spot was " +"found." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:104 +msgid "" +"{ci}Use {cc}/uh tpspawn {0} force{ci} to teleport the player regardless this" +" point." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTPSpawnCommand.java:148 +msgid "" +"{cc}/uh tpspawn <player> [force] {ci}: safely teleports back a player to his" +" spawn location." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:78 +msgid "{ce}This player is not playing or dead!" +msgstr "{ce}玩家不存在或未死亡!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:82 +msgid "" +"{cs}Because {0} is offline, he will be resurrected when he logins. If he " +"was, he is no longer banned." +msgstr "{cs}玩家 {0} 当前离线, 其下次上线时将复活." + +#. Trying to resurrect an alive player +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:90 +msgid "{ce}{0} is not dead!" +msgstr "{ce}玩家 {0} 未死亡!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHResurrectCommand.java:127 +msgid "{cc}/uh resurrect <player> {ci}: resurrects a player." +msgstr "{cc}/uh resurrect <player> {ci}: 复活玩家" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:111 +msgid "" +"{ce}Unable to add the player {0} to the team {1}. This player is unknown in " +"the server." +msgstr "{ce}无法将玩家 {0} 加入到队伍 {1} 中. 服务器中无此玩家." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:119 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:76 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:100 +msgid "{ce}This team does not exists." +msgstr "{ce}指定队伍不存在." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:132 +msgid "{cs}The player {0} was successfully added to the team {1}" +msgstr "{cs}成功将玩家 {0} 加入到队伍 {1} 中." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamJoinCommand.java:178 +msgid "" +"{cc}/uh team join <player> <teamName ...> {ci}: adds a player inside the " +"given team. The name of the team is it color, or the explicit name given." +msgstr "" +"{cc}/uh team join <player> <teamName ...> {ci}: 使玩家加入指定队伍. 使用已设定的队伍颜色或名字进行指定" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:67 +msgid "{cs}All teams where removed." +msgstr "{cs}已删除所有队伍." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamResetCommand.java:93 +msgid "{cc}/uh team reset {ci}: removes all teams." +msgstr "{cc}/uh team reset {ci}: 删除所有队伍" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:79 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:105 +msgid "" +"{ce}Unable to add the team, check the color name. Tip: use Tab to " +"autocomplete." +msgstr "{ce}队伍添加失败, 请检查指定颜色是否正确. 提示: Tab键可自动补全." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:93 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:122 +msgid "{cs}Team {0}{cs} added." +msgstr "{cs}队伍 {0}{cs} 已添加." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamAddCommand.java:164 +msgid "" +"{cc}/uh team add <color> [<name ...>] {ci}: adds a team with the provided " +"color." +msgstr "{cc}/uh team add <color> [<name ...>] {ci}: 增加一个队伍并指定队伍颜色" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:90 +msgid "{ce}The player {0} is disconnected and never logged in before!" +msgstr "{ce}玩家 {0} 已与服务器断开连接, 且再没登录过!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:107 +msgid "{cs}The player {0} was successfully removed from his team." +msgstr "{cs}已将玩家 {0} 从其队伍中删除." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamLeaveCommand.java:141 +msgid "{cc}/uh team leave <player> {ci}: removes a player from his team." +msgstr "{cc}/uh team leave <player> {ci}: 使玩家离队" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:80 +msgid "{cs}Team {0} deleted." +msgstr "{cs}队伍 {0} 已删除." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamRemoveCommand.java:119 +msgid "{cc}/uh team remove <name ...> {ci}: removes a team" +msgstr "{cc}/uh team remove <name ...> {ci}: 删除队伍" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:70 +msgid "{ce}There isn't any team to show." +msgstr "{ce}尚无队伍." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:76 +#, java-format +msgid "{0} ({1} player)" +msgid_plural "{0} ({1} players)" +msgstr[0] "{0} ({1} 位玩家)" + +#. Player name after the online status dot in /uh teams list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:92 +#, java-format +msgctxt "teams_list" +msgid "{0}" +msgstr "{0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamListCommand.java:120 +msgid "{cc}/uh team list {ci}: lists the teams and their players." +msgstr "{cc}/uh team list {ci}: 列出所有队伍及玩家" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamGUICommand.java:80 +msgid "{cc}/uh team gui {ci}: opens a GUI to join and manage the teams." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:70 +msgid "{ce}Cannot toggle the spy mode of {0} because he/she is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:95 +msgid "{cs}Spy mode {darkred}disabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:100 +msgid "{cs}Spy mode {darkgreen}enabled{cs} for {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/team/UHTeamSpyCommand.java:123 +msgid "" +"{cc}/uh team spy [player] {ci}: allows yourself (or the target player) to " +"receive all the team chats (read-only). Execute again to stop." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:92 +msgid "{aqua}------ Timers commands ------" +msgstr "{aqua}------ 计时器指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTimersCommand.java:98 +msgid "{cc}/uh timers {ci}: manages the timers. See /uh timers for details." +msgstr "{cc}/uh timers {ci}: 计时器管理. 输入 /uh timers 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:106 +msgid "{aqua}------ Team commands ------" +msgstr "{aqua}------ 队伍指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:107 +msgid "" +"{cc}/join [player] <team ...> {ci}: adds “player” (or the sender) inside the" +" given team. Without arguments, displays the chat-based team selector." +msgstr "{cc}/join [player] <team ...> {ci}: 加入指定队伍. 若未指定队伍则显示队伍选择信息" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:108 +msgid "" +"{cc}/leave [player] {ci}: removes “player” (or the sender) from his team." +msgstr "{cc}/leave [player] {ci}: 离开队伍" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHTeamCommand.java:115 +msgid "{cc}/uh team {ci}: manages the teams. Execute /uh team for details." +msgstr "{cc}/uh team {ci}: 队伍管理. 输入 /uh team 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:83 +msgid "{aqua}------ Border commands ------" +msgstr "{aqua}------ 边界指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHBorderCommand.java:89 +msgid "{cc}/uh border {ci}: manages borders. Execute /uh border for details." +msgstr "{cc}/uh border {ci}: 边界管理. 输入 /uh border 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:94 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:107 +msgid "{ce}Hey, this is not a number of half-hearts. It's a text. Pfff." +msgstr "{ce}嘿, 你输入的不是数字, 好吗?!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:101 +msgid "{ce}Serial killer!" +msgstr "{ce}你个连环杀人犯!" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:112 +msgid "{ce}The health of {0} was not updated to avoid a kill." +msgstr "{ce}为避免打错指令误杀玩家, {0} 的生命值未改变." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealAllCommand.java:140 +msgid "" +"{cc}/uh healall [half-hearts=20|±diff] {ci}: heals all players instead of " +"only one." +msgstr "{cc}/uh healall [half-hearts=20|±diff] {ci}: 恢复所有玩家的生命值" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:67 +msgid "the console" +msgstr "控制台" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:72 +msgid "" +"{ce}You can't shift the current episode because the game is not started." +msgstr "{ce}游戏尚未开始, 不能更改游戏阶段." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHShiftCommand.java:91 +msgid "{cc}/uh shift {ci}: shifts an episode." +msgstr "{cc}/uh shift {ci}: 更改游戏阶段" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:75 +msgid "{cst}Generating the walls..." +msgstr "{cst}正在生成边界墙..." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:90 +msgid "{ci}From the console, generating the walls of the default world, {0}" +msgstr "{ci}正在从控制台生成世界 {0} 的边界墙." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:100 +msgid "" +"{ce}Unable to generate the wall: see logs for details. The blocks set in the" +" config are probably invalid." +msgstr "{ce}无法生成边界墙: 详情请查看控制台日志. 也许是在配置文件中设置了无效的方块." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:106 +msgid "{ce}An error occurred, see console for details." +msgstr "{ce}发生错误, 详情请查看控制台日志." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:111 +msgid "{cst}Generation done." +msgstr "{cst}边界墙生成完毕." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHGenerateWallsCommand.java:137 +msgid "" +"{cc}/uh generatewalls {ci}: generates the walls according to the " +"configuration." +msgstr "{cc}/uh generatewalls {ci}: 根据配置文件生成边界墙" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:72 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:81 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:72 +msgid "{ce}This timer is not registered." +msgstr "{ce}计时器不存在." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:77 +msgid "{cs}The timer {0}{cs} was stopped." +msgstr "{cs}计时器 {0}{cs} 已停止." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStopCommand.java:102 +msgid "" +"{cc}/uh timers stop <title ...> {ci}: stops a timer. The timer will be " +"removed from the scoreboard." +msgstr "{cc}/uh timers stop <title ...> {ci}: 停止某个计时器. 该计时器将从计分板上删除" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:82 +msgid "{cs}The timer {0}{cs} was started." +msgstr "{cs}计时器 {0}{cs} 已开始." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersStartCommand.java:107 +msgid "{cc}/uh timers start <title ...> {ci}: starts a timer." +msgstr "{cc}/uh timers start <title ...> {ci}: 开始某个计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:76 +msgid "{cs}The timer {0}{cs} is now hidden." +msgstr "{cs}计时器 {0}{cs} 已隐藏." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersHideCommand.java:101 +msgid "" +"{cc}/uh timers hide <title ...> {ci}: removes a timer from the scoreboard. " +"Don't stops the timer." +msgstr "{cc}/uh timers hide <title ...> {ci}: 删除计分板上的计时器, 但该计时器不会停止" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:65 +msgid "{ci}{0} timer is registered." +msgid_plural "{ci}{0} timers are registered." +msgstr[0] "{ci}共 {0} 个计时器." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:73 +msgid "{yellow} • {{ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{yellow} • {{ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{yellow} • {{ci}{0}{ci} - 总计 {1} 秒 - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:81 +msgid "{green} • {ci}{0}{ci} - total {1} second - {2}" +msgid_plural "{green} • {ci}{0}{ci} - total {1} seconds - {2}" +msgstr[0] "{green} • {ci}{0}{ci} - 总计 {1} 秒 - {2}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:90 +msgid "{red} • {ci}{0}{ci} - total {1} second" +msgid_plural "{red} • {ci}{0}{ci} - total {1} seconds" +msgstr[0] "{red} • {ci}{0}{ci} - 总计 {1} 秒" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersListCommand.java:119 +msgid "{cc}/uh timers list {ci}: lists the registered timers." +msgstr "{cc}/uh timers list {ci}: 列出已有的计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:76 +msgid "{cs}The timer {0}{cs} is now displayed." +msgstr "{cs}计时器 {0}{cs} 已显示." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersDisplayCommand.java:101 +msgid "" +"{cc}/uh timers display <title ...> {ci}: displays a timer in the scoreboard." +" Automatic when a timer is started." +msgstr "{cc}/uh timers display <title ...> {ci}: 在计分板上显示计时器. 当一个计时器开始时会自动显示" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:79 +msgid "{cs}The timer {0}{cs} has been deleted." +msgstr "{cs}计时器 {0}{cs} 已删除." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersRemoveCommand.java:104 +msgid "{cc}/uh timers remove <title ...> {ci}: deletes a timer." +msgstr "{cc}/uh timers remove <title ...> {ci}: 删除某个计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:77 +msgid "{cs}The timer {0}{cs} was resumed." +msgstr "{cs}计时器 {0}{cs} 已继续." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersResumeCommand.java:102 +msgid "{cc}/uh timers resume <title ...> {ci}: resumes a timer." +msgstr "{cc}/uh timers resume <title ...> {ci}: 继续某个计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:86 +msgid "{cs}The duration of the timer {0}{cs} is now {1}." +msgstr "{cs}计时器 {0}{cs} 的时长为 {1}." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:91 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:91 +msgid "" +"{ce}The duration' syntax is invalid; accepted formats are mm, mm:ss or " +"hh:mm:ss." +msgstr "{ce}时长格式不正确; 仅接受 mm, mm:ss 或 hh:mm:ss." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersSetCommand.java:124 +msgid "" +"{cc}/uh timers set <duration> <title ...> {ci}: sets the duration of a " +"timer." +msgstr "{cc}/uh timers set <duration> <title ...> {ci}: 设定计时器的时长" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:78 +msgid "{ce}A timer called {0}{ce} already exists; please choose another name." +msgstr "{ce}计时器 {0}{ce} 已存在; 请换个名字." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:86 +msgid "{cs}The timer {0}{cs} (duration {1}) has been registered." +msgstr "{cs}计时器 {0}{cs} (时长 {1}) 已添加." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersAddCommand.java:111 +msgid "{cc}/uh timers add <duration> <title ...> {ci}: adds a timer." +msgstr "{cc}/uh timers add <duration> <title ...> {ci}: 增加一个计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:77 +msgid "{cs}The timer {0}{cs} is now paused." +msgstr "{cs}计时器 {0}{cs} 已暂停." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/timers/UHTimersPauseCommand.java:102 +msgid "{cc}/uh timers pause <title ...> {ci}: pauses a timer." +msgstr "{cc}/uh timers pause <title ...> {ci}: 暂停某个计时器" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:92 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:116 +msgid "{cst}You where frozen by {0}." +msgstr "{cst}你已被 {0} 冻结." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:96 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:121 +msgid "{cst}You where unfrozen by {0}." +msgstr "{cst}你已被 {0} 解冻." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:117 +msgid "{cs}{0} is now frozen." +msgstr "{cs}玩家 {0} 已冻结." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:122 +msgid "{cs}{0} is now unfrozen." +msgstr "{cs}玩家 {0} 已解冻." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:137 +msgid "{darkaqua}The entire game is now frozen." +msgstr "{darkaqua}游戏已冻结." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:141 +msgid "{darkaqua}The game is now unfrozen." +msgstr "{darkaqua}游戏已解冻." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:181 +msgid "{aqua}------ Freeze commands ------" +msgstr "{aqua}------ 冻结指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:182 +msgid "" +"{cc}/uh freeze on [player]{ci}: freezes a player, or the sender without a " +"specified player." +msgstr "{cc}/uh freeze on [player]{ci}: 冻结指定玩家, 若未指定玩家则冻结指令发送者" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:183 +msgid "" +"{cc}/uh freeze off [player]{ci}: unfreezes a player (or the sender), even if" +" the entire game is frozen." +msgstr "{cc}/uh freeze off [player]{ci}: 解冻指定玩家(或指令发送者), 即使游戏已冻结" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:184 +msgid "" +"{cc}/uh freeze all{ci}: freezes the entire game (players, mobs, timer)." +msgstr "{cc}/uh freeze all{ci}: 冻结整个游戏(包括玩家, 怪物, 计时器)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:185 +msgid "" +"{cc}/uh freeze none{ci}: unfreezes the entire game. You NEED to execute this" +" in order to relaunch the timer." +msgstr "{cc}/uh freeze none{ci}: 解冻整个游戏. 若想重启计时器, 使用此指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFreezeCommand.java:192 +msgid "" +"{cc}/uh freeze {ci}: (un)freezes the entire game, or a player. See /uh " +"freeze for details." +msgstr "{cc}/uh freeze {ci}: 冻结(或解冻)玩家或整个游戏. 输入 /uh freeze 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:73 +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:72 +msgid "{ce}This player is offline." +msgstr "{ce}该玩家当前离线." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:115 +msgid "{ce}You can't kill a player with this command, to avoid typo fails." +msgstr "{ce}为避免打错指令, 不能这样杀死玩家." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHHealCommand.java:143 +msgid "" +"{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: heals a player to the " +"number of half-hearts provided (default 20)." +msgstr "{cc}/uh heal <player> [half-hearts=20|±diff] {ci}: 恢复玩家的生命值(默认20点)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHFeedCommand.java:125 +msgid "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: feeds a player." +msgstr "" +"{cc}/uh feed <player> [foodPoints=20] [saturation=max] {ci}: 给玩家增加饥饿值和饱食度" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:77 +msgid "{ce}This player was never seen on this server." +msgstr "{ce}服务器无此玩家." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:92 +msgid "{cs}The player {0} is now marked as dead." +msgstr "{cs}已标记玩家 {0} 为死亡状态." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:96 +msgid "{ce}{0} is not an alive player." +msgstr "{ce}玩家 {0} 非存活状态." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHKillCommand.java:127 +msgid "" +"{cc}/uh kill <player> {ci}: mark a player as dead, even if he is offline." +msgstr "{cc}/uh kill <player> {ci}: 杀死玩家, 即使玩家已离线" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:102 +msgid "" +"{ce}The game is already started! Reload or restart the server to restart the" +" game." +msgstr "{ce}游戏已开始! 要重新开始游戏请重启服务器." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:150 +msgid "{aqua}------ Beginning of the game ------" +msgstr "{aqua}------ 游戏开始指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:151 +msgid "{cc}/uh start {ci}: starts the game. Period." +msgstr "{cc}/uh start {ci}: 直接开始游戏" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:152 +msgid "{aqua}Startup options" +msgstr "{aqua}参数" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:153 +msgid "" +"{ci}You can add some tags to change the way the game is started, just append" +" them to the command with spaces." +msgstr "{ci}你可以用以下参数定义游戏的开始方式, 参数记得用空格分开" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:154 +msgid "" +"{cc}slow:true {ci}: launches the game slowly, in two steps (teleportation " +"then beginning of the game), for smaller servers." +msgstr "{cc}slow:true {ci}: 分两个步骤开始游戏(先传送队伍再开始游戏), 推荐小型服务器使用" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:155 +msgid "" +"{cc}ignoreTeams:true {ci}: even with teams, teleports the players like in a " +"solo game (only one player per spawn point, not a spawn point per team)." +msgstr "{cc}ignoreTeams:true {ci}: 忽略队伍, 以各自为战形式开始游戏(每位玩家占用一个出生点)" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHStartCommand.java:162 +msgid "" +"{cc}/uh start {ci}: launches the game. See /uh start help for options (slow " +"and ignoreTeams)." +msgstr "{cc}/uh start {ci}: 开始游戏. 输入 /uh start help 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:94 +msgid "{cs}The player {0} is now a spectator." +msgstr "{cs}玩家 {0} 已被标记为旁观者." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:115 +msgid "{cs}The player {0} is now a player." +msgstr "{cs}玩家 {0} 已被取消旁观者." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:125 +msgid "{ce}There isn't any spectator to list." +msgstr "{ce}尚无旁观者." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:129 +msgid "{ci}{0} registered spectator." +msgid_plural "{ci}{0} registered spectators." +msgstr[0] "{ci}共 {0} 个旁观者." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:130 +msgid "{ci}This count includes only the initial spectators." +msgstr "{ci}仅统计初始的旁观者." + +#. A list item in the startup spectators list +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:134 +msgctxt "startup_specs" +msgid "{lightpurple} - {0}" +msgstr "{lightpurple} - {0}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:171 +msgid "{aqua}------ Startup spectators commands ------" +msgstr "{aqua}------ 旁观者指令 ------" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:173 +msgid "{cc}/uh spec add <player>{ci}: adds a startup spectator." +msgstr "{cc}/uh spec add <player>{ci}: 增加一个旁观者" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:174 +msgid "{cc}/uh spec remove <player>{ci}: removes a startup spectator." +msgstr "{cc}/uh spec remove <player>{ci}: 删除一个旁观者" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:175 +msgid "{cc}/uh spec list{ci}: lists the startup spectators." +msgstr "{cc}/uh spec list{ci}: 列出所有旁观者" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHSpectatorsCommand.java:183 +msgid "" +"{cc}/uh spec {ci}: manages the spectators. Execute /uh spec for details." +msgstr "{cc}/uh spec {ci}: 旁观者管理. 输入 /uh spec 查看详细指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:63 +msgid "{ce}No rules are set in the config file." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:75 +msgid "{cs}Rules sent to {0}." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:79 +msgid "{ce}Cannot display the rules to {0} because he (or she) is offline." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/uh/UHRulesCommand.java:103 +msgid "" +"{cc}/uh rules [player] {ci}: sends the server rules to the server or the " +"given player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:77 +msgid "{cs}You are now chatting with your team only." +msgstr "{cs}已切换到队伍聊天." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:81 +msgid "{cs}You are now chatting with everyone." +msgstr "{cs}已切换到世界聊天." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/commands/ToggleChatCommand.java:95 +msgid "{cs}You are now chatting with the team {0}{cs}." +msgstr "{cs}已切换到与队伍 {0}{cs} 聊天." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:209 +msgid "" +"{ci}Legend: {cc}/uh command <required> [optional=default] <spaces allowed " +"...>{ci}." +msgstr "{ci}指令示例: {cc}/uh 指令 <必须参数> [可选参数=默认值] <空格分隔多个参数, ...>{ci}" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:225 +msgid "{ce}{bold}You cannot execute this command this way." +msgstr "{ce}{bold}该指令不能这样执行" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:226 +msgid "{ce}The help is displayed above." +msgstr "{ce}帮助文档已在上方显示" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:257 +msgid "{ce}You are not allowed to execute this command." +msgstr "{ce}你没有权限执行此指令" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/commands/core/AbstractCommandExecutor.java:261 +msgid "{ce}This can only be executed as a player." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:65 +msgid "" +"{ce}You are currently out of the future border (diameter of {0} block)." +msgid_plural "" +"{ce}You are currently out of the future border (diameter of {0} blocks)." +msgstr[0] "{ce}你正处于地图新边界外 (新边界直径为 {0} 个方块)." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:69 +msgid "{ce}You are currently out of the future border of {0}×{0} blocks." +msgstr "{ce}你正处于地图新边界外 {0}*{0} 个方块." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/task/BorderWarningTask.java:72 +msgid "{ci}You have {0} block to go before being inside." +msgid_plural "{ci}You have {0} blocks to go before being inside." +msgstr[0] "{ci}还剩 {0} 个方块进入地图新边界内." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:325 +msgid "{ce}Unable to start the game: not enough teleportation spots." +msgstr "{ce}未能开始游戏: 没有足够的出生点." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:326 +msgid "" +"{ci}You can use {cc}/uh spawns generate <random|circular|grid>{ci} to " +"generate the missing spawns automatically." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:399 +msgid "{lightpurple}Teleportation in progress... Please wait." +msgstr "{lightpurple}传送中... 请耐心等候." + +#. Displayed in the action bar while the slow teleportation occurs. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:414 +msgid "{lightpurple}Teleporting... {gray}({0}/{1})" +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:434 +msgid "{gray}Player {0}{gray} teleported." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:486 +msgid "{cs}All teams are teleported." +msgstr "{cs}所有队伍已被传送." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:487 +msgid "{gray}Use {cc}/uh start{gray} or click here to start the game." +msgstr "{gray}请用 {cc}/uh start{gray} 来开始游戏." + +#. Displayed in the action bar when the slow teleportation is finished but the +#. game not started. +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:494 +msgid "{lightpurple}Teleportation complete. {gray}The game will start soon..." +msgstr "" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:525 +msgid "{ce}Please execute {cc}/uh start slow{ce} before." +msgstr "{ce}请先执行 {cc}/uh start slow{ce} 指令." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:531 +msgid "{ce}Please wait while the players are teleported." +msgstr "{ce}正在传送玩家, 请等候." + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:631 +msgid "{red}{bold}Warning!{white} PvP is now enabled." +msgstr "" + +#. The "and" in the winners players list (like "player1, player2 and +#. player3"). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1083 +msgctxt "winners_list" +msgid "and" +msgstr "和" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1095 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} (team {1}{green}) " +"for their victory! {darkgreen}{obfuscated}--" +msgstr "" +"{darkgreen}{obfuscated}--{green}祝贺 {0} (队伍 {1}{green}) " +"赢得胜利!{darkgreen}{obfuscated}--" + +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1099 +msgid "" +"{darkgreen}{obfuscated}--{green} Congratulations to {0} for his victory! " +"{darkgreen}{obfuscated}--" +msgstr "{darkgreen}{obfuscated}--{green}祝贺 {0} 赢得胜利!{darkgreen}{obfuscated}--" + +#. The main title of the /title displayed when a team wins the game. {0} +#. becomes the team display name (with colors). +#. The main title of the /title displayed when a player wins the game (in +#. solo). {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1111 +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1118 +msgid "{darkgreen}{0}" +msgstr "" + +#. The subtitle of the /title displayed when a team wins the game. {0} becomes +#. the team display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1113 +msgid "{green}This team wins the game!" +msgstr "" + +#. The subtitle of the /title displayed when a player wins the game (in solo). +#. {0} becomes the player display name (with colors). +#: src/main/java/eu/carrade/amaury/UHCReloaded/game/UHGameManager.java:1120 +msgid "{green}wins the game!" +msgstr "" diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2315c61..68e3024 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: UHPlugin -description: Ultra Hardcore plugin -main: me.azenet.UHPlugin.UHPlugin -version: 1.3 §cdev +description: UltraHardcore Reloaded +main: eu.carrade.amaury.UHCReloaded.UHCReloaded +version: 1.4 author: "Amaury Carrade" authors: [azenet, "João Roda"] @@ -17,26 +17,30 @@ softdepend: commands: uh: description: UltraHardcore Reloaded base command - usage: /uh <subcommand> - see /uh for available subcommands. + usage: /<command> <subcommand> - see /<command> for available subcommands. t: description: Allows an user to send a message to his team. - usage: /t <message> - + usage: /<command> <message> + g: description: Allows an user to send a message to everyone. - usage: /g <message> - + usage: /<command> <message> + togglechat: description: Allows an user to toggle the chat between the global chat and a team chat. - usage: /togglechat - + usage: /<command> + join: description: Use this to join an UltraHardcore team. - usage: /join [player] <team> - + usage: /<command> [player] <team> + leave: description: Use this to quit your current UltraHardcore team. - usage: /leave [player] + usage: /<command> [player] + + teams: + description: Displays a GUI to manage the UHCReloaded teams + usage: /<command> permissions: @@ -64,8 +68,11 @@ permissions: uh.spec: true uh.finish: true uh.infos: true + uh.rules: true uh.timers: true uh.tp: true + uh.team.spy: true + uh.team.spy.others: true uh.teamchat: true uh.player: true @@ -82,6 +89,12 @@ permissions: uh.team: description: Allows an user to manage the teams with /uh team * default: op + uh.team.spy: + description: Allows an user to receive all teams chat if he executes /uh team spy + default: op + uh.team.spy.others: + description: Allows an user to toggle spy for another player; this other one will receive all the teams chat. + default: op uh.spawns: description: Allows an user to manage the spawn points with /uh spawns * default: op @@ -130,6 +143,9 @@ permissions: uh.infos: description: Allows an user to get infos about the current game with /uh infos default: true + uh.rules: + description: Allows an user to broadcast or send the rules on-demand + default: op uh.about: description: Prints some informations about the plugin and the translation. default: true @@ -158,6 +174,8 @@ permissions: children: uh.player.join: true uh.player.leave: true + uh.player.renameTeam: true + uh.team.gui: true uh.player.join.*: @@ -165,6 +183,7 @@ permissions: children: uh.player.join.self: true uh.player.join.others: true + uh.team.gui: true uh.player.join.self: description: Allows a player to use /join <team> (changes his own team). @@ -179,6 +198,7 @@ permissions: children: uh.player.leave.self: true uh.player.leave.others: true + uh.team.gui: true uh.player.leave.self: description: Allows a player to use /leave (quits his own team). @@ -186,3 +206,14 @@ permissions: uh.player.leave.others: description: Allows a player to use /leave <player>. default: op + + + uh.player.renameTeam: + default: Allows a player to rename his own team. + default: op + + + uh.team.gui: + description: Allows a player to use the teams GUI (/uh team gui) + default: true + diff --git a/src/test/java/eu/carrade/amaury/UHCReloaded/TestsUtils.java b/src/test/java/eu/carrade/amaury/UHCReloaded/TestsUtils.java new file mode 100644 index 0000000..c6393d0 --- /dev/null +++ b/src/test/java/eu/carrade/amaury/UHCReloaded/TestsUtils.java @@ -0,0 +1,119 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded; + +import fr.zcraft.zlib.components.configuration.Configuration; +import fr.zcraft.zlib.components.configuration.ConfigurationItem; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.i18n.I18n; +import fr.zcraft.zlib.core.ZLib; +import org.bukkit.configuration.file.FileConfiguration; +import org.mockito.Matchers; +import org.powermock.api.mockito.PowerMockito; + +import java.util.Locale; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +public class TestsUtils +{ + private static boolean staticPluginMocked = false; + private static boolean i18nMocked = false; + + public static void mockConfig() + { + PowerMockito.mockStatic(UHConfig.class); + PowerMockito.mockStatic(ConfigurationItem.class); + + Configuration.init(UHConfig.class); + } + + public static void mockI18n() + { + if (i18nMocked) + return; + + PowerMockito.mockStatic(I18n.class); + PowerMockito.mockStatic(I.class); + + when(I18n.getPrimaryLocale()).thenReturn(Locale.FRANCE); + when(I18n.getFallbackLocale()).thenReturn(Locale.US); + when(I18n.getLastTranslator(Matchers.any(Locale.class))).thenReturn(""); + when(I18n.getTranslationTeam(Matchers.any(Locale.class))).thenReturn(""); + when(I18n.getReportErrorsTo(Matchers.any(Locale.class))).thenReturn(""); + + when(I.t(Matchers.anyString(), Matchers.any())).thenReturn(""); + when(I.tc(Matchers.anyString(), Matchers.anyString(), Matchers.any())).thenReturn(""); + when(I.tn(Matchers.anyString(), Matchers.anyString(), Matchers.anyInt(), Matchers.any())).thenReturn(""); + when(I.tcn(Matchers.anyString(), Matchers.anyString(), Matchers.anyString(), Matchers.anyInt(), Matchers.any())).thenReturn(""); + + i18nMocked = true; + } + + public static void mockStaticPlugin() + { + if (staticPluginMocked) + return; + + final UHCReloaded pluginInstance = getMockedPluginInstance(); + + PowerMockito.mockStatic(UHCReloaded.class); + when(UHCReloaded.get()).thenReturn(pluginInstance); + + ZLib.init(pluginInstance); + + staticPluginMocked = true; + } + + public static UHCReloaded getMockedPluginInstance() + { + final FileConfiguration config = mock(FileConfiguration.class); + when(config.get(Matchers.anyString())).thenReturn(null); + when(config.get(Matchers.anyString(), Matchers.anyObject())).thenReturn(null); + when(config.getBoolean(Matchers.anyString())).thenReturn(true); + when(config.getBoolean(Matchers.anyString(), Matchers.anyBoolean())).thenReturn(true); + when(config.getInt(Matchers.anyString())).thenReturn(0); + when(config.getInt(Matchers.anyString(), Matchers.anyInt())).thenReturn(0); + when(config.getDouble(Matchers.anyString())).thenReturn(0d); + when(config.getDouble(Matchers.anyString(), Matchers.anyDouble())).thenReturn(0d); + when(config.getString(Matchers.anyString())).thenReturn(""); + when(config.getString(Matchers.anyString(), Matchers.anyString())).thenReturn(""); + when(config.getConfigurationSection(Matchers.anyString())).thenReturn(config); + + final UHCReloaded uhcReloaded = mock(UHCReloaded.class); + when(uhcReloaded.getConfig()).thenReturn(config); + + return uhcReloaded; + } +} diff --git a/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java b/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java new file mode 100644 index 0000000..4fc7115 --- /dev/null +++ b/src/test/java/eu/carrade/amaury/UHCReloaded/commands/TestCommandsAnnotation.java @@ -0,0 +1,86 @@ +/* + * Copyright or © or Copr. Amaury Carrade (2014 - 2016) + * + * http://amaury.carrade.eu + * + * This software is governed by the CeCILL-B license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-B + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-B license and that you accept its terms. + */ +package eu.carrade.amaury.UHCReloaded.commands; + +import eu.carrade.amaury.UHCReloaded.TestsUtils; +import eu.carrade.amaury.UHCReloaded.UHCReloaded; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommand; +import eu.carrade.amaury.UHCReloaded.commands.core.AbstractCommandExecutor; +import eu.carrade.amaury.UHCReloaded.commands.core.annotations.Command; +import fr.zcraft.zlib.components.i18n.I; +import fr.zcraft.zlib.components.i18n.I18n; +import junit.framework.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.HashSet; +import java.util.Set; + + +@RunWith(PowerMockRunner.class) +@PrepareForTest({UHCReloaded.class, I18n.class, I.class}) +public class TestCommandsAnnotation +{ + @Test + public void testCommandAnnotationIsPresentEverywhere() + { + TestsUtils.mockStaticPlugin(); + TestsUtils.mockI18n(); + TestsUtils.mockConfig(); + + // Data + Set<AbstractCommandExecutor> executors = new HashSet<>(); + executors.add(new UHCommandExecutor(TestsUtils.getMockedPluginInstance())); + + // Tests + for(AbstractCommandExecutor executor : executors) + for (AbstractCommand command : executor.getMainCommands().values()) + testCommandAnnotationIsPresentEverywhere(command); + } + + /** + * Recursively tests if the command annotation is present on every registered class. + * + * @param command The command to start with. + */ + private void testCommandAnnotationIsPresentEverywhere(AbstractCommand command) + { + Assert.assertTrue("Missing command annotation for the class " + command.getClass().getCanonicalName(), command.getClass().isAnnotationPresent(Command.class)); + + for(AbstractCommand subCommand : command.getSubcommands().values()) + { + testCommandAnnotationIsPresentEverywhere(subCommand); + } + } +}