diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/.poggit.yml b/.poggit.yml deleted file mode 100644 index 7fa00b5..0000000 --- a/.poggit.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/PMMPPlugin/Humanoid -branches: -- master -projects: - Humanoid: - path: "" - icon: meta/icon/192x192.png -... diff --git a/LICENSE b/LICENSE index 3ffc567..d1d7d46 100644 --- a/LICENSE +++ b/LICENSE @@ -1,661 +1,21 @@ -GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are 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. - - 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. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - 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 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 work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero 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 Affero 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 Affero 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 Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. \ No newline at end of file +MIT License + +Copyright (c) 2018 PresentKim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 58173c7..ecbee93 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,16 @@ -[![Telegram](https://img.shields.io/badge/Telegram-PresentKim-blue.svg?logo=telegram)](https://t.me/PresentKim) - -[![icon/192x192](meta/icon/192x192.png?raw=true)]() - -[![License](https://img.shields.io/github/license/PMMPPlugin/Humanoid.svg?label=License)](LICENSE) -[![Poggit](https://poggit.pmmp.io/ci.shield/PMMPPlugin/Humanoid/Humanoid)](https://poggit.pmmp.io/ci/PMMPPlugin/Humanoid) -[![Release](https://img.shields.io/github/release/PMMPPlugin/Humanoid.svg?label=Release)](https://github.com/PMMPPlugin/Humanoid/releases/latest) -[![Download](https://img.shields.io/github/downloads/PMMPPlugin/Humanoid/total.svg?label=Download)](https://github.com/PMMPPlugin/Humanoid/releases/latest) - - +# Humanoid +__A plugin for [PMMP](https://pmmp.io) :: Add humanoid entity!__ + +[![license](https://img.shields.io/github/license/organization/Humanoid.svg?label=License)](https://github.com/organization/Humanoid/blob/master/LICENSE) +[![release](https://img.shields.io/github/release/organization/Humanoid.svg?label=Release)](https://github.com/organization/Humanoid/releases/latest) +[![download](https://img.shields.io/github/downloads/organization/Humanoid/total.svg?label=Download)](https://github.com/organization/Humanoid/releases/latest) +[![Build status](https://ci.appveyor.com/api/projects/status/xd18ryl4li9rc11m/branch/master?svg=true)](https://ci.appveyor.com/project/PresentKim/humanoid-pmmp/branch/master) + +## What is this? A plugin add humanoid entity for PocketMine-MP ## Command -Main command : `/humanoid ` +Main command : `/humanoid ` | subcommand | arguments | description | | ---------- | ---------------------- | --------------------------- | @@ -20,26 +19,20 @@ Main command : `/humanoid | Load default lang file | -| Reload | | Reload all data | -| Save | | Save all data | ## Permission -| permission | default | description | -| ------------------- | -------- | ------------------ | -| humanoid.cmd | OP | main command | -| | | | -| humanoid.cmd.add | OP | add subcommand | -| humanoid.cmd.set | OP | set subcommand | -| humanoid.cmd.remove | OP | remove subcommand | -| humanoid.cmd.copy | OP | copy subcommand | -| humanoid.cmd.cancel | OP | cancel subcommand | -| humanoid.cmd.lang | OP | lang subcommand | -| humanoid.cmd.reload | OP | reload subcommand | -| humanoid.cmd.save | OP | save subcommand | +| permission | default | description | +| ---------------------- | -------- | -------------------- | +| humanoid.cmd | OP | main command | +| | | | +| humanoid.cmd.add | OP | add subcommand | +| humanoid.cmd.set | OP | set subcommand | +| humanoid.cmd.remove | OP | remove subcommand | +| humanoid.cmd.copy | OP | copy subcommand | +| humanoid.cmd.cancel | OP | cancel subcommand | @@ -47,24 +40,16 @@ Main command : `/humanoid list ex) `/humanoid Set List 2` -| name | arguments | description | -| ---------- | -------------------------------- | ------------------------------- | -| List | \[page\] | Show data name list | -| Name | \[name\] | Change humanoid's name | -| Rotation | * or \ \ | Change humanoid's yaw and pitch | -| Item | * or \ \[item meta\] | Change humanoid's held item | -| Skin | * or \ | Change humanoid's skin | -| Geometry | \ | Change humanoid's geometry name | -| Sneak | | Toggle humanoid's sneaking | -| Position | * or \ or \ \ \ \[world name\] | Change humanoid's position | -| Scale | \ | Change humanoid's scale | - - - - -## ChangeLog -### v1.0.0 [![Source](https://img.shields.io/badge/source-v1.0.0-blue.png?label=source)](https://github.com/PMMPPlugin/Humanoid/tree/v1.0.0) [![Release](https://img.shields.io/github/downloads/PMMPPlugin/Humanoid/v1.0.0/total.png?label=download&colorB=1fadad)](https://github.com/PMMPPlugin/Humanoid/releases/v1.0.0) -- First release -### v1.0.1 [![Source](https://img.shields.io/badge/source-v1.0.1-blue.png?label=source)](https://github.com/PMMPPlugin/Humanoid/tree/v1.0.0) [![Release](https://img.shields.io/github/downloads/PMMPPlugin/Humanoid/v1.0.1/total.png?label=download&colorB=1fadad)](https://github.com/PMMPPlugin/Humanoid/releases/v1.0.1) -- \[Added\] Softdepend https://github.com/PMMPPlugin/GeometryAPI -- \[Fixed\] Humanoid : get geometry data from GeometryAPI \ No newline at end of file +| name | arguments | description | +| ---------- | --------------------------------------------------- | ------------------------------- | +| List | \[page\] | Show data name list | +| Name | \[name\] | Change humanoid's name | +| Rotation | \ \ | Change humanoid's yaw and pitch | +| Item | \[item id\] | Change humanoid's held item | +| Armor | \[item id\] | Change humanoid's Armor | +| Skin | \[player name\] | Change humanoid's skin data | +| Cape | \[player name\] | Change humanoid's cape data | +| Geometry | \[geometry name\] | Change humanoid's geometry name | +| Sneak | | Toggle humanoid's sneaking | +| Position | \ or \ \ \ \[world name\] | Change humanoid's position | +| Scale | \ | Change humanoid's scale | diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..5c50f97 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,68 @@ +#---------------------------------# +# Info of configure the PM-plugin # +#---------------------------------# +# @author : PresentKim +# @version : 1.1.0 +# @url : https://github.com/organization/ExamplePlugin-AppVeyor/blob/master/appveyor.yml + +#---------------------------------# +# general configuration # +#---------------------------------# +# version format +version: "#{build}" + +# branches to build +branches: + # whitelist + only: + - master + +# Skipping commits with particular message or from specific user +skip_commits: + files: + - README.md + +# Maximum number of concurrent jobs for the project +max_jobs: 1 + + +#---------------------------------# +# environment configuration # +#---------------------------------# + +# Build worker image (VM template) +image: Ubuntu1804 + +# set clone depth +clone_depth: 5 + +# environment variables +environment: + APPVEYOR_BUILD_URL: "https://ci.appveyor.com/project/${APPVEYOR_ACCOUNT_NAME}/${APPVEYOR_PROJECT_NAME}/builds/${APPVEYOR_BUILD_ID}" + BUILD_SCRIPT_URL: "https://raw.githubusercontent.com/organization/ExamplePlugin-AppVeyor/master/build.php" + +# build cache to preserve files/folders between builds +cache: + - '$HOME/cache/' # my cache + +# scripts that are called at very beginning, before repo cloning +init: + - mkdir $HOME/cache/ + +# scripts that run after cloning repository +install: + - wget -nc -P $HOME/cache/ https://jenkins.pmmp.io/job/PHP-7.3-Linux-x86_64/lastSuccessfulBuild/artifact/PHP_Linux-x86_64.tar.gz + - tar -C ../ -xvf $HOME/cache/PHP_Linux-x86_64.tar.gz + - wget --cache=off --cookies=off ${BUILD_SCRIPT_URL} + +# to run your custom scripts instead of automatic MSBuild +build_script: + - ../bin/php7/bin/php ./build.php --buildurl=${APPVEYOR_BUILD_URL} --buildnum=${APPVEYOR_BUILD_NUMBER} + + +#---------------------------------# +# artifacts configuration # +#---------------------------------# + +artifacts: + - path: "releases/*.phar" diff --git a/assets/screenshot/screenshot_1.jpg b/assets/screenshot/screenshot_1.jpg new file mode 100644 index 0000000..a2e11f4 Binary files /dev/null and b/assets/screenshot/screenshot_1.jpg differ diff --git a/assets/screenshot/screenshot_2.jpg b/assets/screenshot/screenshot_2.jpg new file mode 100644 index 0000000..452bdc5 Binary files /dev/null and b/assets/screenshot/screenshot_2.jpg differ diff --git a/assets/screenshot/screenshot_3.jpg b/assets/screenshot/screenshot_3.jpg new file mode 100644 index 0000000..e1667ac Binary files /dev/null and b/assets/screenshot/screenshot_3.jpg differ diff --git a/assets/screenshot/screenshot_4.jpg b/assets/screenshot/screenshot_4.jpg new file mode 100644 index 0000000..69c5190 Binary files /dev/null and b/assets/screenshot/screenshot_4.jpg differ diff --git a/assets/screenshot/screenshot_5.jpg b/assets/screenshot/screenshot_5.jpg new file mode 100644 index 0000000..72cb530 Binary files /dev/null and b/assets/screenshot/screenshot_5.jpg differ diff --git a/meta/icon/144x144.png b/meta/icon/144x144.png deleted file mode 100644 index fc4270e..0000000 Binary files a/meta/icon/144x144.png and /dev/null differ diff --git a/meta/icon/192x192.png b/meta/icon/192x192.png deleted file mode 100644 index bebae11..0000000 Binary files a/meta/icon/192x192.png and /dev/null differ diff --git a/meta/icon/36x36.png b/meta/icon/36x36.png deleted file mode 100644 index 988b464..0000000 Binary files a/meta/icon/36x36.png and /dev/null differ diff --git a/meta/icon/48x48.png b/meta/icon/48x48.png deleted file mode 100644 index 04e9177..0000000 Binary files a/meta/icon/48x48.png and /dev/null differ diff --git a/meta/icon/72x72.png b/meta/icon/72x72.png deleted file mode 100644 index 0859213..0000000 Binary files a/meta/icon/72x72.png and /dev/null differ diff --git a/meta/icon/96x96.png b/meta/icon/96x96.png deleted file mode 100644 index 6307471..0000000 Binary files a/meta/icon/96x96.png and /dev/null differ diff --git a/meta/screenshot/screenshot_1.jpg b/meta/screenshot/screenshot_1.jpg deleted file mode 100644 index 91a6895..0000000 Binary files a/meta/screenshot/screenshot_1.jpg and /dev/null differ diff --git a/meta/screenshot/screenshot_2.jpg b/meta/screenshot/screenshot_2.jpg deleted file mode 100644 index fc38617..0000000 Binary files a/meta/screenshot/screenshot_2.jpg and /dev/null differ diff --git a/meta/screenshot/screenshot_3.jpg b/meta/screenshot/screenshot_3.jpg deleted file mode 100644 index 19ce912..0000000 Binary files a/meta/screenshot/screenshot_3.jpg and /dev/null differ diff --git a/plugin.yml b/plugin.yml index a142594..c25d0c3 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,36 +1,31 @@ --- -name: Humanoid -main: presentkim\humanoid\HumanoidMain -version: 1.0.1 -api: [3.0.0, 3.0.0-ALPHA10] -author: PresentKim -load: STARTUP -softdepend: ['GeometryAPI'] +name: Humanoid +main: kim\present\humanoid\Humanoid +version: 1.0.6 +api: [3.0.0, 3.0.0-ALPHA10, 3.0.0-ALPHA11, 3.0.0-ALPHA12, 4.0.0] +author: PresentKim +description: Add humanoid entity +load: STARTUP +softdepend: ['GeometryAPI'] permissions: humanoid.cmd: - description: Humanoid main command - default: op + description: Humanoid main command + default: op children: humanoid.cmd.add: - description: Humanoid command - add - default: op + description: Humanoid command - add + default: op humanoid.cmd.set: - description: Humanoid command - set - default: op + description: Humanoid command - set + default: op humanoid.cmd.remove: - description: Humanoid command - remove - default: op + description: Humanoid command - remove + default: op humanoid.cmd.copy: - description: Humanoid command - copy - default: op + description: Humanoid command - copy + default: op humanoid.cmd.cancel: - description: Humanoid command - cancel - default: op - humanoid.cmd.lang: - description: Humanoid command - lang - default: op - humanoid.cmd.reload: - description: Humanoid command - reload - default: op -... + description: Humanoid command - cancel + default: op +... \ No newline at end of file diff --git a/resources/lang/eng.yml b/resources/lang/eng.yml index dd1babc..db5e400 100644 --- a/resources/lang/eng.yml +++ b/resources/lang/eng.yml @@ -2,26 +2,20 @@ prefix: "[Humanoid] " humanoid-add@success: "Humanoid was created" +humanoid-set@success: "Humanoid's data was changed" humanoid-remove@success: "Humanoid was removed" humanoid-copy@success-copy: "Touch the block to paste humanoid" humanoid-copy@success-paste: "Humanoid was copied" -humanoid-set-name@success: "Humanoid's name was setted to {%0}" -humanoid-set-rotation@success: "Humanoid's rotation was setted to {%0}:{%1}" -humanoid-set-item@success: "Humanoid's item was changed" -humanoid-set-skin@success: "Humanoid's skin was changed" -humanoid-set-geometry@success: "Humanoid's geometry was setted to {%0}" -humanoid-set-sneak@success: "Humanoid's sneaking was changed" -humanoid-set-position@success: "Humanoid's position was changed" -humanoid-set-scale@success: "Humanoid's scale was setted to {%0}" - command-generic-failure@in-game: "Available in game only" command-generic-failure@permission: "You do not have permission to use this command" command-generic-failure@invalid: "{%0} is invalid value" command-generic-failure@invalid-player: "{%0} is invalid player name" +command-generic-failure@invalid-item: "{%0} is invalid item id" command-humanoid: "humanoid" -command-humanoid@usage: "/humanoid " +command-humanoid@usage: "/humanoid <{%0}>" +command-humanoid@usage-separator: " | " command-humanoid@description: "Main command of Humanoid" command-humanoid@aliases: ["hm"] @@ -43,23 +37,32 @@ command-humanoid-set-list@item: " - {%1}" command-humanoid-set-list@aliases: ["l"] command-humanoid-set-name: "name" -command-humanoid-set-name@usage: "/humanoid Set Name " +command-humanoid-set-name@usage: "/humanoid Set Name [name]" command-humanoid-set-name@aliases: ["n"] command-humanoid-set-rotation: "rotation" -command-humanoid-set-rotation@usage: "/humanoid Set Rotation {* | }" +command-humanoid-set-rotation@usage: "/humanoid Set Rotation " command-humanoid-set-rotation@aliases: ["r"] command-humanoid-set-item: "item" -command-humanoid-set-item@usage: "/humanoid Set Item {* | [item meta]}" +command-humanoid-set-item@usage: "/humanoid Set Item [item id]" command-humanoid-set-item@aliases: ["i"] +command-humanoid-set-armor: "armor" +command-humanoid-set-armor@usage: "/humanoid Set Armor [item id]" +command-humanoid-set-armor@failure: "{%0} is not armor" +command-humanoid-set-armor@aliases: ["a"] + command-humanoid-set-skin: "skin" command-humanoid-set-skin@usage: "/humanoid Set Skin [player name]" command-humanoid-set-skin@aliases: ["s"] +command-humanoid-set-cape: "cape" +command-humanoid-set-cape@usage: "/humanoid Set Cape [player name]" +command-humanoid-set-cape@aliases: ["c"] + command-humanoid-set-geometry: "geometry" -command-humanoid-set-geometry@usage: "/humanoid Set Geometry " +command-humanoid-set-geometry@usage: "/humanoid Set Geometry [geometry name]" command-humanoid-set-geometry@aliases: ["g"] command-humanoid-set-sneak: "sneak" @@ -89,15 +92,4 @@ command-humanoid-cancel@usage: "/humanoid cancel" command-humanoid-cancel@success: "Act was cancelled" command-humanoid-cancel@failure: "You don't have any act" command-humanoid-cancel@aliases: ["c"] - -command-humanoid-lang: "lang" -command-humanoid-lang@usage: "/humanoid Lang " -command-humanoid-lang@success: "{%0} language file was loaded" -command-humanoid-lang@failure: "{%0} is invalid language prefix" -command-humanoid-lang@aliases: ["language"] - -command-humanoid-reload: "reload" -command-humanoid-reload@usage: "/humanoid Reload" -command-humanoid-reload@success: "All data was reloaded" -command-humanoid-reload@aliases: ["rl"] ... \ No newline at end of file diff --git a/resources/lang/kor.yml b/resources/lang/kor.yml index 2df99a9..5882db4 100644 --- a/resources/lang/kor.yml +++ b/resources/lang/kor.yml @@ -2,26 +2,20 @@ prefix: "[Humanoid] " humanoid-add@success: "휴머노이드가 생성되었습니다" +humanoid-set@success: "휴머노이드의 데이터가 변경되었습니다" humanoid-remove@success: "휴머노이드가 제거되었습니다" humanoid-copy@success-copy: "휴머노이드를 붙여넣기할 블럭을 터치해주세요" humanoid-copy@success-paste: "휴머노이드가 복사되었습니다" -humanoid-set-name@success: "휴머노이드의 이름이 {%0}로 설정되었습니다" -humanoid-set-rotation@success: "휴머노이드의 방향이 {%0}:{%1}로 설정되었습니다" -humanoid-set-item@success: "휴머노이드의 아이템이 변경되었습니다" -humanoid-set-skin@success: "휴머노이드의 스킨이 변경되었습니다" -humanoid-set-geometry@success: "휴머노이드의 geometry가 {%0}로 설정되었습니다" -humanoid-set-sneak@success: "휴머노이드의 웅크리기가 변경되었습니다" -humanoid-set-position@success: "휴머노이드의 위치가 변경되었습니다" -humanoid-set-scale@success: "휴머노이드의 크기가 {%0}로 설정되었습니다" - command-generic-failure@in-game: "게임 내에서만 사용할 수 있습니다" command-generic-failure@permission: "이 명령을 사용할 수 있는 권한이 없습니다" command-generic-failure@invalid: "{%0}는 잘못된 값입니다" command-generic-failure@invalid-player: "{%0}는 잘못된 플레이어 명입니다" +command-generic-failure@invalid-item: "{%0}는 잘못된 아이템 id입니다" command-humanoid: "humanoid" -command-humanoid@usage: "/humanoid " +command-humanoid@usage: "/humanoid <{%0}>" +command-humanoid@usage-separator: " | " command-humanoid@description: "Humanoid의 메인 명령어" command-humanoid@aliases: ["hm"] @@ -43,23 +37,32 @@ command-humanoid-set-list@item: " - {%1}" command-humanoid-set-list@aliases: ["l"] command-humanoid-set-name: "name" -command-humanoid-set-name@usage: "/humanoid Set Name <이름>" +command-humanoid-set-name@usage: "/humanoid Set Name [이름]" command-humanoid-set-name@aliases: ["n"] command-humanoid-set-rotation: "rotation" -command-humanoid-set-rotation@usage: "/humanoid Set Rotation {* | }" +command-humanoid-set-rotation@usage: "/humanoid Set Rotation " command-humanoid-set-rotation@aliases: ["r"] command-humanoid-set-item: "item" -command-humanoid-set-item@usage: "/humanoid Set Item {* | <아이템id> [아이템meta]}" +command-humanoid-set-item@usage: "/humanoid Set Item [아이템id]" command-humanoid-set-item@aliases: ["i"] +command-humanoid-set-armor: "armor" +command-humanoid-set-armor@usage: "/humanoid Set Armor [아이템id]" +command-humanoid-set-armor@failure: "{%0}는 갑옷이 아닙니다" +command-humanoid-set-armor@aliases: ["a"] + command-humanoid-set-skin: "skin" command-humanoid-set-skin@usage: "/humanoid Set Skin [플레이어명]" command-humanoid-set-skin@aliases: ["s"] +command-humanoid-set-cape: "cape" +command-humanoid-set-cape@usage: "/humanoid Set Cape [플레이어명]" +command-humanoid-set-cape@aliases: ["c"] + command-humanoid-set-geometry: "geometry" -command-humanoid-set-geometry@usage: "/humanoid Set Geometry " +command-humanoid-set-geometry@usage: "/humanoid Set Geometry [geometry명]" command-humanoid-set-geometry@aliases: ["g"] command-humanoid-set-sneak: "sneak" @@ -89,15 +92,4 @@ command-humanoid-cancel@usage: "/humanoid cancel" command-humanoid-cancel@success: "행동이 취소되었습니다" command-humanoid-cancel@failure: "취소할 행동이 없습니다" command-humanoid-cancel@aliases: ["c"] - -command-humanoid-lang: "lang" -command-humanoid-lang@usage: "/humanoid Lang <언어명>" -command-humanoid-lang@success: "{%0}언어 파일을 불러왔습니다" -command-humanoid-lang@failure: "{%0}는 잘못된 언어명입니다" -command-humanoid-lang@aliases: ["language"] - -command-humanoid-reload: "reload" -command-humanoid-reload@usage: "/humanoid Reload" -command-humanoid-reload@success: "모든 데이터를 불러왔습니다" -command-humanoid-reload@aliases: ["rl"] ... \ No newline at end of file diff --git a/src/kim/present/humanoid/Humanoid.php b/src/kim/present/humanoid/Humanoid.php new file mode 100644 index 0000000..d0d6dab --- /dev/null +++ b/src/kim/present/humanoid/Humanoid.php @@ -0,0 +1,102 @@ +getResource('lang/eng.yml'), true); + + Entity::registerEntity(HumanoidEntity::class, true, [ + 'Humanoid', + 'PresentKim:humanoid', + ]); + } + } + + /** + * Called when the plugin is enabled + */ + public function onEnable() : void{ + $dataFolder = $this->getDataFolder(); + if(!file_exists($dataFolder)){ + mkdir($dataFolder, 0777, true); + } + $langfilename = $dataFolder . 'lang.yml'; + if(!file_exists($langfilename)){ + $resource = $this->getResource('lang/eng.yml'); + fwrite($fp = fopen("{$dataFolder}lang.yml", "wb"), $contents = stream_get_contents($resource)); + fclose($fp); + Translation::loadFromContents($contents); + }else{ + Translation::load($langfilename); + } + + self::$prefix = Translation::translate('prefix'); + + if($this->command == null){ + $this->command = new PoolCommand($this, 'humanoid'); + $this->command->createSubCommand(AddSubCommand::class); + $this->command->createSubCommand(SetSubCommand::class); + $this->command->createSubCommand(RemoveSubCommand::class); + $this->command->createSubCommand(CopySubCommand::class); + $this->command->createSubCommand(CancelSubCommand::class); + } + $this->command->updateTranslation(); + $this->command->updateSudCommandTranslation(); + if($this->command->isRegistered()){ + $this->getServer()->getCommandMap()->unregister($this->command); + } + $this->getServer()->getCommandMap()->register(strtolower($this->getName()), $this->command); + + foreach(SetSubCommand::getSubCommands() as $key => $value){ + $value->updateTranslation(); + } + + $this->getServer()->getPluginManager()->registerEvents(new DataPacketEventListener(), $this); + $this->getServer()->getPluginManager()->registerEvents(new PlayerEventListener(), $this); + } + + /** + * @param string $name = '' + * + * @return PoolCommand + */ + public function getCommand(string $name = '') : PoolCommand{ + return $this->command; + } + + /** @param PoolCommand $command */ + public function setCommand(PoolCommand $command) : void{ + $this->command = $command; + } +} diff --git a/src/kim/present/humanoid/act/ClickHumanoidAct.php b/src/kim/present/humanoid/act/ClickHumanoidAct.php new file mode 100644 index 0000000..920d953 --- /dev/null +++ b/src/kim/present/humanoid/act/ClickHumanoidAct.php @@ -0,0 +1,12 @@ +player = $player; + } + + /** + * @return PlayerAct[] + */ + public static function getActs() : array{ + return PlayerAct::$acts; + } + + /** + * @param Player $player + * + * @return PlayerAct|null + */ + public static function getAct(Player $player) : ?PlayerAct{ + return PlayerAct::$acts[$player->getLowerCaseName()] ?? null; + } + + public static function cancelAllAct() : void{ + PlayerAct::$acts = []; + } + + public function register() : void{ + self::registerAct($this); + } + + /** + * @param PlayerAct $task + */ + public static function registerAct(PlayerAct $task) : void{ + PlayerAct::$acts[$task->getKey()] = $task; + } + + /** + * @return string + */ + public function getKey() : string{ + return $this->player->getLowerCaseName(); + } + + public function cancel() : void{ + self::cancelAct($this); + } + + /** + * @param PlayerAct $task + */ + public static function cancelAct(PlayerAct $task) : void{ + unset(PlayerAct::$acts[$task->getKey()]); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/AddHumanoidAct.php b/src/kim/present/humanoid/act/child/AddHumanoidAct.php new file mode 100644 index 0000000..a73efde --- /dev/null +++ b/src/kim/present/humanoid/act/child/AddHumanoidAct.php @@ -0,0 +1,50 @@ +name = $name; + } + + /** + * @param PlayerInteractEvent $event + */ + public function onInteract(PlayerInteractEvent $event) : void{ + if($event->getAction() === PlayerInteractEvent::RIGHT_CLICK_AIR){ + $nbt = Entity::createBaseNBT($this->player, null, $this->player->yaw, $this->player->pitch); + }else{ + $nbt = Entity::createBaseNBT($event->getBlock()->add(0.5, 1, 0.5)); + $nbt->setTag($this->player->getInventory()->getItemInHand()->nbtSerialize(-1, 'HeldItem')); + } + $skin = $this->player->getSkin(); + $nbt->setString('SkinData', $skin->getSkinData()); + $nbt->setString('GeometryName', $skin->getGeometryName()); + $nbt->setString('CustomName', $this->name); + + $entity = Entity::createEntity('Humanoid', $this->player->level, $nbt); + $entity->spawnToAll(); + + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-add@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/CopyHumanoidAct.php b/src/kim/present/humanoid/act/child/CopyHumanoidAct.php new file mode 100644 index 0000000..7dad6a0 --- /dev/null +++ b/src/kim/present/humanoid/act/child/CopyHumanoidAct.php @@ -0,0 +1,26 @@ +cancel(); + $humanoid = $event->getHumanoid(); + $humanoid->saveNBT(); + PlayerAct::registerAct(new PasteHumanoidAct($this->player, clone $humanoid->namedtag)); + + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-copy@success-copy')); + + $event->setCancelled(true); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/PasteHumanoidAct.php b/src/kim/present/humanoid/act/child/PasteHumanoidAct.php new file mode 100644 index 0000000..f377a73 --- /dev/null +++ b/src/kim/present/humanoid/act/child/PasteHumanoidAct.php @@ -0,0 +1,49 @@ +nbt = $nbt; + } + + /** + * @param PlayerInteractEvent $event + */ + public function onInteract(PlayerInteractEvent $event) : void{ + $pos = $event->getAction() === PlayerInteractEvent::RIGHT_CLICK_AIR ? $this->player->asPosition() : $pos = $event->getBlock(); + $this->nbt->setTag(new ListTag("Pos", [ + new DoubleTag("", $pos->x), + new DoubleTag("", $pos->y), + new DoubleTag("", $pos->z), + ])); + + $entity = Entity::createEntity('Humanoid', $pos->level, $this->nbt); + $entity->spawnToAll(); + + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-copy@success-paste')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/RemoveHumanoidAct.php b/src/kim/present/humanoid/act/child/RemoveHumanoidAct.php new file mode 100644 index 0000000..10ac76e --- /dev/null +++ b/src/kim/present/humanoid/act/child/RemoveHumanoidAct.php @@ -0,0 +1,24 @@ +getHumanoid()->kill(); + + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-remove@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidArmorAct.php b/src/kim/present/humanoid/act/child/SetHumanoidArmorAct.php new file mode 100644 index 0000000..fbcc485 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidArmorAct.php @@ -0,0 +1,48 @@ +item = $item; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $humanoid = $event->getHumanoid(); + $inventory = $humanoid->getInventory(); + $index = $inventory->getIndex($this->item); + if($index === HumanoidInventory::HELDITEM){ + $this->player->sendMessage(Plugin::$prefix . Translation::translate('command-humanoid-set-armor@failure', $this->item->getName())); + }else{ + $armor = $inventory->getItem($index); + if($armor->equals($this->item, true, true)){ + $inventory->clear($index); + }else{ + $inventory->setItem($index, $this->item); + } + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + } + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidCapeAct.php b/src/kim/present/humanoid/act/child/SetHumanoidCapeAct.php new file mode 100644 index 0000000..2e9066f --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidCapeAct.php @@ -0,0 +1,37 @@ +skin = $skin; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $humanoid = $event->getHumanoid(); + $humanoidSkin = $humanoid->getSkin(); + $humanoid->setSkin(new Skin('humanoid', $humanoidSkin->getSkinData(), $this->skin->getCapeData(), $humanoidSkin->getGeometryName())); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidGeometryAct.php b/src/kim/present/humanoid/act/child/SetHumanoidGeometryAct.php new file mode 100644 index 0000000..0ca0039 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidGeometryAct.php @@ -0,0 +1,37 @@ +geometryName = $geometryName; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $humanoid = $event->getHumanoid(); + $humanoidSkin = $humanoid->getSkin(); + $humanoid->setSkin(new Skin('humanoid', $humanoidSkin->getSkinData(), $humanoidSkin->getCapeData(), $this->geometryName)); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidItemAct.php b/src/kim/present/humanoid/act/child/SetHumanoidItemAct.php new file mode 100644 index 0000000..95c3838 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidItemAct.php @@ -0,0 +1,35 @@ +item = $item; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $event->getHumanoid()->getInventory()->setHeldItem($this->item); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidNameAct.php b/src/kim/present/humanoid/act/child/SetHumanoidNameAct.php new file mode 100644 index 0000000..a75e15c --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidNameAct.php @@ -0,0 +1,34 @@ +name = $name; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $event->getHumanoid()->setNameTag($this->name); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidPositionAct.php b/src/kim/present/humanoid/act/child/SetHumanoidPositionAct.php new file mode 100644 index 0000000..6cd81d5 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidPositionAct.php @@ -0,0 +1,35 @@ +pos = $pos; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $event->getHumanoid()->teleport($this->pos); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidRotationAct.php b/src/kim/present/humanoid/act/child/SetHumanoidRotationAct.php new file mode 100644 index 0000000..b2118f4 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidRotationAct.php @@ -0,0 +1,41 @@ +yaw = $yaw; + $this->pitch = $pitch; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $this->yaw = $this->yaw ?? $this->player->yaw; + $this->pitch = $this->pitch ?? $this->player->pitch; + $event->getHumanoid()->setRotation($this->yaw, $this->pitch); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidScaleAct.php b/src/kim/present/humanoid/act/child/SetHumanoidScaleAct.php new file mode 100644 index 0000000..cc02c25 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidScaleAct.php @@ -0,0 +1,34 @@ +scale = $scale; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $event->getHumanoid()->setScale($this->scale * 0.01); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/SetHumanoidSkinAct.php b/src/kim/present/humanoid/act/child/SetHumanoidSkinAct.php new file mode 100644 index 0000000..1df4ef5 --- /dev/null +++ b/src/kim/present/humanoid/act/child/SetHumanoidSkinAct.php @@ -0,0 +1,37 @@ +skin = $skin; + } + + /** @param PlayerClickHumanoidEvent $event */ + public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ + $humanoid = $event->getHumanoid(); + $humanoidSkin = $humanoid->getSkin(); + $humanoid->setSkin(new Skin('humanoid', $this->skin->getSkinData(), $humanoidSkin->getCapeData(), $humanoidSkin->getGeometryName())); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/act/child/ToggleHumanoidSneakAct.php b/src/kim/present/humanoid/act/child/ToggleHumanoidSneakAct.php new file mode 100644 index 0000000..672e5d7 --- /dev/null +++ b/src/kim/present/humanoid/act/child/ToggleHumanoidSneakAct.php @@ -0,0 +1,24 @@ +getHumanoid(); + $humanoid->setSneaking(!$humanoid->isSneaking()); + $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set@success')); + + $event->setCancelled(true); + $this->cancel(); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/PoolCommand.php b/src/kim/present/humanoid/command/PoolCommand.php new file mode 100644 index 0000000..c44b0a8 --- /dev/null +++ b/src/kim/present/humanoid/command/PoolCommand.php @@ -0,0 +1,118 @@ +setExecutor($this); + + $reflection = new \ReflectionClass(Command::class); + $this->property = $reflection->getProperty('name'); + $this->property->setAccessible(true); + + $this->uname = $name; + $this->setPermission("{$name}.cmd"); + $this->updateTranslation(); + + $this->subCommands = $subCommands; + } + + public function updateTranslation() : void{ + $this->property->setValue($this, Translation::translate("command-{$this->uname}")); + $this->description = Translation::translate("command-{$this->uname}@description"); + $this->usageMessage = $this->getUsage(new ConsoleCommandSender()); + $aliases = Translation::getArray("command-{$this->uname}@aliases"); + if(is_array($aliases)){ + $this->setAliases($aliases); + } + } + + /** + * @param CommandSender|null $sender + * + * @return string + */ + public function getUsage(CommandSender $sender = null) : string{ + if($sender === null){ + return $this->usageMessage; + }else{ + $subCommands = []; + foreach($this->subCommands as $key => $subCommand){ + if($subCommand->checkPermission($sender)){ + $subCommands[] = $subCommand->getLabel(); + } + } + return Translation::translate("command-{$this->uname}@usage", implode(Translation::translate("command-{$this->uname}@usage-separator"), $subCommands)); + } + } + + /** + * @param CommandSender $sender + * @param Command $command + * @param string $label + * @param string[] $args + * + * @return bool + */ + public function onCommand(CommandSender $sender, Command $command, string $label, array $args) : bool{ + if(isset($args[0])){ + $label = array_shift($args); + foreach($this->subCommands as $key => $value){ + if($value->checkLabel($label)){ + $value->execute($sender, $args); + return true; + } + } + } + $sender->sendMessage($this->getPlugin()->getServer()->getLanguage()->translateString("commands.generic.usage", [$this->getUsage($sender)])); + return true; + } + + /** + * @return SubCommand[] + */ + public function getSubCommands() : array{ + return $this->subCommands; + } + + /** + * @param SubCommand[] $subCommands + */ + public function setSubCommands(SubCommand ...$subCommands) : void{ + $this->subCommands = $subCommands; + } + + /** + * @param SubCommand::class $subCommandClass + */ + public function createSubCommand($subCommandClass) : void{ + $this->subCommands[] = new $subCommandClass($this); + } + + public function updateSudCommandTranslation() : void{ + foreach($this->subCommands as $key => $value){ + $value->updateTranslation(); + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/SimpleSubCommand.php b/src/kim/present/humanoid/command/SimpleSubCommand.php new file mode 100644 index 0000000..6ba278e --- /dev/null +++ b/src/kim/present/humanoid/command/SimpleSubCommand.php @@ -0,0 +1,98 @@ +uname = $uname; + + $this->updateTranslation(); + } + + public function updateTranslation() : void{ + $this->label = Translation::translate("command-humanoid-set-{$this->uname}"); + $this->aliases = Translation::getArray("command-humanoid-set-{$this->uname}@aliases"); + $this->usage = Translation::translate("command-humanoid-set-{$this->uname}@usage"); + } + + /** + * @param CommandSender $sender + * @param String[] $args + * + * @return bool + */ + abstract public function onCommand(CommandSender $sender, array $args) : bool; + + /** + * @param string $label + * + * @return bool + */ + public function checkLabel(string $label) : bool{ + return strcasecmp($label, $this->label) === 0 || $this->aliases && Utils::in_arrayi($label, $this->aliases); + } + + /** + * @return string + */ + public function getLabel() : string{ + return $this->label; + } + + /** + * @param string $label + */ + public function setLabel(string $label) : void{ + $this->label = $label; + } + + /** + * @return string[] + */ + public function getAliases() : array{ + return $this->aliases; + } + + /** + * @param string[] $aliases + */ + public function setAliases(array $aliases) : void{ + $this->aliases = $aliases; + } + + /** + * @return string + */ + public function getUsage() : string{ + return $this->usage; + } + + /** + * @param string $usage + */ + public function setUsage(string $usage) : void{ + $this->usage = $usage; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/SubCommand.php b/src/kim/present/humanoid/command/SubCommand.php new file mode 100644 index 0000000..45db976 --- /dev/null +++ b/src/kim/present/humanoid/command/SubCommand.php @@ -0,0 +1,150 @@ +owner = $owner; + $this->plugin = $owner->getPlugin(); + + $this->strId = "command-{$owner->uname}-{$label}"; + $this->permission = "{$owner->uname}.cmd.{$label}"; + + $this->updateTranslation(); + } + + public function updateTranslation() : void{ + $this->label = Translation::translate($this->strId); + $this->aliases = Translation::getArray("{$this->strId}@aliases"); + $this->usage = $this->translate('usage'); + } + + /** + * @param string $tag + * @param string[] $params + * + * @return string + */ + public function translate(string $tag, string ...$params) : string{ + return Translation::translate("{$this->strId}@{$tag}", ...$params); + } + + /** + * @param CommandSender $sender + * @param String[] $args + */ + public function execute(CommandSender $sender, array $args) : void{ + if(!$this->checkPermission($sender)){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@permission')); + }elseif(!$this->onCommand($sender, $args)){ + $sender->sendMessage(Server::getInstance()->getLanguage()->translateString("commands.generic.usage", [$this->usage])); + } + } + + /** + * @param CommandSender $target + * + * @return bool + */ + public function checkPermission(CommandSender $target) : bool{ + if($this->permission === null){ + return true; + }else{ + return $target->hasPermission($this->permission); + } + } + + /** + * @param CommandSender $sender + * @param String[] $args + * + * @return bool + */ + abstract public function onCommand(CommandSender $sender, array $args) : bool; + + /** + * @param string $label + * + * @return bool + */ + public function checkLabel(string $label) : bool{ + return strcasecmp($label, $this->label) === 0 || $this->aliases && Utils::in_arrayi($label, $this->aliases); + } + + /** + * @return string + */ + public function getLabel() : string{ + return $this->label; + } + + /** + * @param string $label + */ + public function setLabel(string $label) : void{ + $this->label = $label; + } + + /** + * @return string[] + */ + public function getAliases() : array{ + return $this->aliases; + } + + /** + * @param string[] $aliases + */ + public function setAliases(array $aliases) : void{ + $this->aliases = $aliases; + } + + /** + * @return string + */ + public function getUsage() : string{ + return $this->usage; + } + + /** + * @param string $usage + */ + public function setUsage(string $usage) : void{ + $this->usage = $usage; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/AddSubCommand.php b/src/kim/present/humanoid/command/subcommands/AddSubCommand.php new file mode 100644 index 0000000..c8a2e01 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/AddSubCommand.php @@ -0,0 +1,40 @@ +getNameTag())); + $sender->sendMessage(Plugin::$prefix . $this->translate('success')); + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + } + return true; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/CancelSubCommand.php b/src/kim/present/humanoid/command/subcommands/CancelSubCommand.php new file mode 100644 index 0000000..4f0f575 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/CancelSubCommand.php @@ -0,0 +1,44 @@ +cancel(); + $sender->sendMessage(Plugin::$prefix . $this->translate('success')); + }else{ + $sender->sendMessage(Plugin::$prefix . $this->translate('failure')); + } + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + } + return true; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/CopySubCommand.php b/src/kim/present/humanoid/command/subcommands/CopySubCommand.php new file mode 100644 index 0000000..9cf5d37 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/CopySubCommand.php @@ -0,0 +1,40 @@ +sendMessage(Plugin::$prefix . $this->translate('success')); + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + } + return true; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/RemoveSubCommand.php b/src/kim/present/humanoid/command/subcommands/RemoveSubCommand.php new file mode 100644 index 0000000..af0091c --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/RemoveSubCommand.php @@ -0,0 +1,40 @@ +sendMessage(Plugin::$prefix . $this->translate('success')); + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + } + return true; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/SetSubCommand.php b/src/kim/present/humanoid/command/subcommands/SetSubCommand.php new file mode 100644 index 0000000..a000913 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/SetSubCommand.php @@ -0,0 +1,81 @@ + $value){ + if($value->checkLabel($label)){ + if($value->onCommand($sender, $args)){ + $sender->sendMessage(Plugin::$prefix . $this->translate('success')); + } + return true; + } + } + $sender->sendMessage(Plugin::$prefix . $this->translate('failure', $label)); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetArmorCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetArmorCommand.php new file mode 100644 index 0000000..e6e6d2c --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetArmorCommand.php @@ -0,0 +1,52 @@ +getInventory()->getItemInHand(); + }else{ + $item = ItemFactory::fromString($args[0]); + if($item->isNull()){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-item', $args[0])); + return false; + } + } + if($item instanceof Armor){ + PlayerAct::registerAct(new SetHumanoidArmorAct($sender, $item)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-humanoid-set-armor@failure', $item->getName())); + return false; + } + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetCapeCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetCapeCommand.php new file mode 100644 index 0000000..c2556b6 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetCapeCommand.php @@ -0,0 +1,48 @@ +getSkin(); + }else{ + $player = Server::getInstance()->getPlayer($args[0]); + if($player === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-player', $args[0])); + return false; + }else{ + $skin = $player->getSkin(); + } + } + PlayerAct::registerAct(new SetHumanoidCapeAct($sender, $skin)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetGeometryCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetGeometryCommand.php new file mode 100644 index 0000000..216bca1 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetGeometryCommand.php @@ -0,0 +1,41 @@ +getSkin()->getGeometryName(); + }else{ + $geometryName = implode('_', $args); + } + PlayerAct::registerAct(new SetHumanoidGeometryAct($sender, $geometryName)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetItemCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetItemCommand.php new file mode 100644 index 0000000..73e9768 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetItemCommand.php @@ -0,0 +1,46 @@ +getInventory()->getItemInHand(); + }else{ + $item = ItemFactory::fromString($args[0]); + if($item->isNull()){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-item', $args[0])); + return false; + } + } + PlayerAct::registerAct(new SetHumanoidItemAct($sender, $item)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetNameCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetNameCommand.php new file mode 100644 index 0000000..d5d3e10 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetNameCommand.php @@ -0,0 +1,36 @@ +sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetPositionCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetPositionCommand.php new file mode 100644 index 0000000..bfd6c97 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetPositionCommand.php @@ -0,0 +1,78 @@ +asPosition(); + }elseif(!isset($args[1])){ + $player = Server::getInstance()->getPlayer($args[0]); + if($player === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-player', $args[0])); + return false; + }else{ + $pos = $player->asPosition(); + } + }elseif(isset($args[2])){ + $x = is_numeric($args[0]) ? (float) $args[0] : null; + if($x === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); + return false; + } + $y = is_numeric($args[1]) ? (float) $args[1] : null; + if($y === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[1])); + return false; + } + $z = is_numeric($args[2]) ? (float) $args[2] : null; + if($z === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[2])); + return false; + } + if(isset($args[3])){ + $level = Server::getInstance()->getLevelByName($args[3]); + if($level === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[3])); + return false; + } + }else{ + $level = $sender->getLevel(); + } + $pos = new Position($x, $y, $z, $level); + }else{ + $sender->sendMessage(Server::getInstance()->getLanguage()->translateString("commands.generic.usage", [$this->usage])); + return false; + } + PlayerAct::registerAct(new SetHumanoidPositionAct($sender, $pos)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetRotationCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetRotationCommand.php new file mode 100644 index 0000000..efe5bfd --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetRotationCommand.php @@ -0,0 +1,54 @@ +yaw; + $pitch = $sender->pitch; + }elseif(isset($args[1])){ + $yaw = is_numeric($args[0]) ? (float) $args[0] : null; + $pitch = is_numeric($args[1]) ? (float) $args[1] : null; + if($yaw === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); + return false; + }elseif($pitch === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[1])); + return false; + } + }else{ + $sender->sendMessage(Server::getInstance()->getLanguage()->translateString("commands.generic.usage", [$this->usage])); + return false; + } + PlayerAct::registerAct(new SetHumanoidRotationAct($sender, $yaw, $pitch)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetScaleCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetScaleCommand.php new file mode 100644 index 0000000..d06aa3b --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetScaleCommand.php @@ -0,0 +1,53 @@ += 10; + }); + if($scale === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); + return false; + }else{ + PlayerAct::registerAct(new SetHumanoidScaleAct($sender, $scale)); + return true; + } + }else{ + $sender->sendMessage(Server::getInstance()->getLanguage()->translateString("commands.generic.usage", [$this->usage])); + return false; + } + }else{ + + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetSkinCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetSkinCommand.php new file mode 100644 index 0000000..6741869 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetSkinCommand.php @@ -0,0 +1,48 @@ +getSkin(); + }else{ + $player = Server::getInstance()->getPlayer($args[0]); + if($player === null){ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-player', $args[0])); + return false; + }else{ + $skin = $player->getSkin(); + } + } + PlayerAct::registerAct(new SetHumanoidSkinAct($sender, $skin)); + return true; + }else{ + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/SetSneakCommand.php b/src/kim/present/humanoid/command/subcommands/simple/SetSneakCommand.php new file mode 100644 index 0000000..10c28b0 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/SetSneakCommand.php @@ -0,0 +1,36 @@ +sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); + return false; + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/command/subcommands/simple/ShowListCommand.php b/src/kim/present/humanoid/command/subcommands/simple/ShowListCommand.php new file mode 100644 index 0000000..88aa3f8 --- /dev/null +++ b/src/kim/present/humanoid/command/subcommands/simple/ShowListCommand.php @@ -0,0 +1,46 @@ + $value){ + $list[] = [ + $value->getLabel(), + $value->getUsage(), + ]; + } + + $max = ceil(count($list) / 5); + $page = min($max, (isset($args[0]) ? Utils::toInt($args[0], 1, function(int $i){ + return $i > 0 ? 1 : -1; + }) : 1) - 1); + $sender->sendMessage(Plugin::$prefix . Translation::translate('command-humanoid-set-list@head', $page + 1, $max)); + for($i = $page * 5; $i < ($page + 1) * 5 && $i < count($list); $i++){ + $sender->sendMessage(Translation::translate('command-humanoid-set-list@item', ...$list[$i])); + } + return false; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/entity/Humanoid.php b/src/kim/present/humanoid/entity/Humanoid.php new file mode 100644 index 0000000..9a583ed --- /dev/null +++ b/src/kim/present/humanoid/entity/Humanoid.php @@ -0,0 +1,203 @@ +inventory; + } + + /** + * @return Skin + */ + public function getSkin() : Skin{ + return $this->skin; + } + + /** + * @param Skin $skin + */ + public function setSkin(Skin $skin) : void{ + if(!$skin->isValid()){ + throw new \InvalidStateException('Specified skin is not valid, must be 8KiB or 16KiB'); + } + + if(empty($skin->getGeometryData()) && class_exists(GeometryAPI::class)){ + $geometryData = GeometryAPI::getInstance()->getGeometryData($geometryName = $skin->getGeometryName()) ?? ''; + $skin = new Skin($skin->getSkinId(), $skin->getSkinData(), $skin->getCapeData(), $geometryName, $geometryData); + } + $this->skin = $skin; + $this->skin->debloatGeometryData(); + $this->sendSkin($this->getViewers()); + } + + public function saveNBT() : void{ + parent::saveNBT(); + + $this->namedtag->setTag($this->inventory->nbtSerialize()); + $this->namedtag->setTag(new CompoundTag('Skin', [ + new StringTag('SkinData', $this->skin->getSkinData()), + new StringTag('CapeData', $this->skin->getCapeData()), + new StringTag('GeometryName', $this->skin->getGeometryName()), + ])); + $this->namedtag->setTag(new ByteTag('Sneak', (int) $this->isSneaking())); + $this->namedtag->setTag(new FloatTag('Scale', $this->getScale())); + } + + /** + * @param EntityDamageEvent $source + */ + public function attack(EntityDamageEvent $source) : void{ + $source->setCancelled(true); + } + + /** + * @param float $dx + * @param float $dy + * @param float $dz + * + * @return bool + */ + public function move(float $dx, float $dy, float $dz) : void{ + } + + /** + * @param Vector3 $pos + * @param float|null $yaw + * @param float|null $pitch + * + * @return bool + */ + public function teleport(Vector3 $pos, float $yaw = null, float $pitch = null) : bool{ + if(parent::teleport($pos, $yaw, $pitch)){ + $yaw = $yaw ?? $this->yaw; + $pitch = $pitch ?? $this->pitch; + + $pk = new MovePlayerPacket(); + $pk->entityRuntimeId = $this->getId(); + $pk->position = $this->getOffsetPosition($pos); + $pk->pitch = $pitch; + $pk->headYaw = $yaw; + $pk->yaw = $yaw; + $pk->mode = MovePlayerPacket::MODE_TELEPORT; + + $this->server->broadcastPacket($targets ?? $this->hasSpawned, $pk); + $this->spawnToAll(); + return true; + } + return false; + } + + protected function initEntity() : void{ + parent::initEntity(); + + $this->uuid = UUID::fromRandom(); + + if($this->namedtag->hasTag('Inventory')){ + $this->inventory = HumanoidInventory::nbtDeserialize($this, $this->namedtag->getCompoundTag('Inventory')); + }else{ + $this->inventory = new HumanoidInventory($this); + $this->inventory->setHeldItem($this->namedtag->hasTag('HeldItem') ? Item::nbtDeserialize($this->namedtag->getCompoundTag('HeldItem')) : Item::get(Item::AIR)); + + $this->namedtag->removeTag('HeldItem'); + } + if($this->namedtag->hasTag('Skin')){ + $skinTag = $this->namedtag->getCompoundTag('Skin'); + $skinData = $skinTag->getString('SkinData'); + $capeData = $skinTag->getString('CapeData'); + $geometryName = $skinTag->getString('GeometryName'); + }else{ + $skinData = $this->namedtag->hasTag('SkinData') ? $this->namedtag->getString('SkinData') : str_repeat("\x00", 8192); + $capeData = ''; + $geometryName = $this->namedtag->hasTag('GeometryName') ? $this->namedtag->getString('GeometryName') : ''; + + $this->namedtag->removeTag('SkinData'); + $this->namedtag->removeTag('GeometryName'); + } + $this->setSkin(new Skin('humanoid', $skinData, $capeData, $geometryName)); + $this->setSneaking($this->namedtag->hasTag('Sneak') ? (bool) $this->namedtag->getByte('Sneak') : false); + $this->setScale($this->namedtag->hasTag('Scale') ? $this->namedtag->getFloat('Scale') : 1); + } + + /** + * @param Player $player + */ + protected function sendSpawnPacket(Player $player) : void{ + if(!$this->skin->isValid()){ + throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . ' must have a valid skin set'); + } + + $pk = new AddPlayerPacket(); + $pk->uuid = $this->getUniqueId(); + $pk->username = $this->getNameTag(); + $pk->entityRuntimeId = $this->id; + $pk->position = $this->asVector3(); + $pk->motion = null; + $pk->yaw = $this->yaw; + $pk->pitch = $this->pitch; + $pk->item = $this->inventory->getHeldItem(); + $pk->metadata = $this->propertyManager->getAll(); + $player->dataPacket($pk); + + $this->inventory->sendArmors($player); + $this->sendSkin([$player]); + } + + /** + * @return UUID + */ + public function getUniqueId() : UUID{ + return $this->uuid; + } + + /** + * @param Player[]|null $targets + */ + public function sendSkin(array $targets = null) : void{ + $pk = new PlayerSkinPacket(); + $pk->uuid = $this->getUniqueId(); + $pk->skin = $this->skin; + $this->server->broadcastPacket($targets ?? $this->hasSpawned, $pk); + } +} diff --git a/src/kim/present/humanoid/event/PlayerClickHumanoidEvent.php b/src/kim/present/humanoid/event/PlayerClickHumanoidEvent.php new file mode 100644 index 0000000..ac567ac --- /dev/null +++ b/src/kim/present/humanoid/event/PlayerClickHumanoidEvent.php @@ -0,0 +1,51 @@ +player = $player; + $this->humanoid = $humanoid; + $this->action = $action; + } + + /** + * @return Humanoid + */ + public function getHumanoid() : Humanoid{ + return $this->humanoid; + } + + /** + * @return int + */ + public function getAction() : int{ + return $this->action; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/inventory/HumanoidInventory.php b/src/kim/present/humanoid/inventory/HumanoidInventory.php new file mode 100644 index 0000000..680812d --- /dev/null +++ b/src/kim/present/humanoid/inventory/HumanoidInventory.php @@ -0,0 +1,233 @@ +holder = $holder; + parent::__construct(); + } + + /** + * @param Humanoid $humanoid + * @param CompoundTag $tag + * + * @return HumanoidInventory + */ + public static function nbtDeserialize(Humanoid $humanoid, CompoundTag $tag) : HumanoidInventory{ + $inventory = new HumanoidInventory($humanoid); + $inventory->setHelmet(Item::nbtDeserialize($tag->getCompoundTag('Helmet'))); + $inventory->setChestplate(Item::nbtDeserialize($tag->getCompoundTag('Chestplate'))); + $inventory->setLeggings(Item::nbtDeserialize($tag->getCompoundTag('Leggings'))); + $inventory->setBoots(Item::nbtDeserialize($tag->getCompoundTag('Boots'))); + $inventory->setHeldItem(Item::nbtDeserialize($tag->getCompoundTag('HeldItem'))); + return $inventory; + } + + /** + * @param Item $item + * + * @return bool + */ + public function setHelmet(Item $item) : bool{ + return $this->setItem(self::HELMET, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setChestplate(Item $item) : bool{ + return $this->setItem(self::CHESTPLATE, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setLeggings(Item $item) : bool{ + return $this->setItem(self::LEGGINGS, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setBoots(Item $item) : bool{ + return $this->setItem(self::BOOTS, $item); + } + + /** + * @param Item $item + * + * @return bool + */ + public function setHeldItem(Item $item) : bool{ + return $this->setItem(self::HELDITEM, $item); + } + + /** @return Humanoid */ + public function getHolder() : Humanoid{ + return $this->holder; + } + + /** @return string */ + public function getName() : string{ + return "HumanoidInventory"; + } + + /** @return int */ + public function getDefaultSize() : int{ + return 5; + } + + /** + * @param int $index + * @param Player|Player[] $target + */ + public function sendSlot(int $index, $target) : void{ + if($index === self::HELDITEM){ + $this->sendHeldItem($target); + }else{ + $this->sendArmors($target); + } + } + + /** @param Player|Player[] $target */ + public function sendHeldItem($target) : void{ + if($target instanceof Player){ + $target = [$target]; + } + $pk = new MobEquipmentPacket(); + $pk->entityRuntimeId = $this->holder->getId(); + $pk->item = $this->getHeldItem(); + $pk->inventorySlot = $pk->hotbarSlot = 0; + $pk->windowId = ContainerIds::INVENTORY; + $pk->encode(); + + foreach($target as $player){ + $player->dataPacket($pk); + } + } + + /** @return Item */ + public function getHeldItem() : Item{ + return $this->getItem(self::HELDITEM); + } + + /** @param Player|Player[] $target */ + public function sendArmors($target) : void{ + if($target instanceof Player){ + $target = [$target]; + } + $armor = $this->getContents(true); + + $pk = new MobArmorEquipmentPacket(); + $pk->entityRuntimeId = $this->holder->getId(); + $pk->slots = $armor; + $pk->encode(); + + foreach($target as $player){ + $player->dataPacket($pk); + } + } + + public function canAddItem(Item $item) : bool{ + return $this->getItem($this->getIndex($item))->isNull(); + } + + public function getIndex(Item $item){ + $class = get_class($item); + if(Utils::endsWith($class, 'Helmet') || Utils::endsWith($class, 'Cap')){ + return self::HELMET; + }elseif(Utils::endsWith($class, 'Chestplate') || Utils::endsWith($class, 'Tunic')){ + return self::CHESTPLATE; + }elseif(Utils::endsWith($class, 'Leggings') || Utils::endsWith($class, 'Pants')){ + return self::LEGGINGS; + }elseif(Utils::endsWith($class, 'Boots')){ + return self::BOOTS; + }else{ + return self::HELDITEM; + } + } + + public function addItem(Item ...$slots) : array{ + $itemSlots = []; + foreach($slots as $slot){ + if($slot->isNull()){ + $itemSlots[] = clone $slot; + }else{ + $index = $this->getIndex($slot); + if($this->getItem($index)->isNull()){ + $this->setItem($index, $slot); + }else{ + $itemSlots[] = clone $slot; + } + } + } + return $itemSlots; + } + + /** @return Player[] */ + public function getViewers() : array{ + return array_merge(parent::getViewers(), $this->holder->getViewers()); + } + + /** + * @param string $tagName + * + * @return CompoundTag + */ + public function nbtSerialize(string $tagName = 'Inventory') : CompoundTag{ + return new CompoundTag($tagName, [ + $this->getHelmet()->nbtSerialize(self::HELMET, 'Helmet'), + $this->getChestplate()->nbtSerialize(self::CHESTPLATE, 'Chestplate'), + $this->getLeggings()->nbtSerialize(self::LEGGINGS, 'Leggings'), + $this->getBoots()->nbtSerialize(self::BOOTS, 'Boots'), + $this->getHeldItem()->nbtSerialize(self::HELDITEM, 'HeldItem'), + ]); + } + + /** @return Item */ + public function getHelmet() : Item{ + return $this->getItem(self::HELMET); + } + + /** @return Item */ + public function getChestplate() : Item{ + return $this->getItem(self::CHESTPLATE); + } + + /** @return Item */ + public function getLeggings() : Item{ + return $this->getItem(self::LEGGINGS); + } + + /** @return Item */ + public function getBoots() : Item{ + return $this->getItem(self::BOOTS); + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/listener/DataPacketEventListener.php b/src/kim/present/humanoid/listener/DataPacketEventListener.php new file mode 100644 index 0000000..8e7dbd0 --- /dev/null +++ b/src/kim/present/humanoid/listener/DataPacketEventListener.php @@ -0,0 +1,38 @@ +owner = Plugin::getInstance(); + } + + /** @param DataPacketReceiveEvent $event */ + public function onDataPacketReceiveEvent(DataPacketReceiveEvent $event) : void{ + $pk = $event->getPacket(); + if($pk instanceof InventoryTransactionPacket){ + if($pk->transactionType === InventoryTransactionPacket::TYPE_USE_ITEM_ON_ENTITY){ + $player = $event->getPlayer(); + $target = $player->level->getEntity($pk->trData->entityRuntimeId); + if($target instanceof Humanoid){ + $event->setCancelled(true); + Server::getInstance()->getPluginManager()->callEvent(new PlayerClickHumanoidEvent($player, $target, $pk->trData->actionType)); + } + } + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/listener/PlayerEventListener.php b/src/kim/present/humanoid/listener/PlayerEventListener.php new file mode 100644 index 0000000..f433528 --- /dev/null +++ b/src/kim/present/humanoid/listener/PlayerEventListener.php @@ -0,0 +1,51 @@ +owner = Plugin::getInstance(); + } + + /** + * @priority LOW + * + * @param PlayerClickHumanoidEvent $event + */ + public function onPlayerClickHumanoidEvent(PlayerClickHumanoidEvent $event) : void{ + if(!$event->isCancelled()){ + $task = PlayerAct::getAct($player = $event->getPlayer()); + if($task instanceof ClickHumanoidAct){ + $task->onClickHumanoid($event); + } + } + } + + /** + * @priority LOW + * + * @param PlayerInteractEvent $event + */ + public function onPlayerInteractEvent(PlayerInteractEvent $event) : void{ + if(!$event->isCancelled()){ + $task = PlayerAct::getAct($player = $event->getPlayer()); + if($task instanceof InteractAct){ + $task->onInteract($event); + } + } + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/util/Translation.php b/src/kim/present/humanoid/util/Translation.php new file mode 100644 index 0000000..b908d5b --- /dev/null +++ b/src/kim/present/humanoid/util/Translation.php @@ -0,0 +1,90 @@ +getLogger()->debug("get $strId from default"); + $value = self::$default[$strId]; + }else{ + Plugin::getInstance()->getLogger()->critical("get $strId failed"); + return "Undefined strId : $strId"; + } + + if(is_array($value)){ + $value = $value[array_rand($value)]; + } + if(is_string($value)){ + return empty($params) ? $value : strtr($value, Utils::listToPairs($params)); + }else{ + return "$strId is not string"; + } + } + + /** + * @param string $strId + * + * @return string[]|null + */ + public static function getArray(string $strId) : ?array{ + if(isset(self::$lang[$strId])){ + $value = self::$lang[$strId]; + }elseif(isset(self::$default[$strId])){ + Plugin::getInstance()->getLogger()->debug("get $strId from default"); + $value = self::$default[$strId]; + }else{ + Plugin::getInstance()->getLogger()->critical("get $strId failed"); + return null; + } + return is_array($value) ? $value : null; + } +} \ No newline at end of file diff --git a/src/kim/present/humanoid/util/Utils.php b/src/kim/present/humanoid/util/Utils.php new file mode 100644 index 0000000..1c2a63b --- /dev/null +++ b/src/kim/present/humanoid/util/Utils.php @@ -0,0 +1,74 @@ + $value){ + if(strcasecmp($str, $value) === 0){ + return true; + } + } + return false; + } + + /** + * @param Object[] $list + * + * @return string[] + */ + public static function listToPairs(array $list) : array{ + $pairs = []; + $size = sizeOf($list); + for($i = 0; $i < $size; ++$i){ + $pairs["{%$i}"] = $list[$i]; + } + return $pairs; + } + + /** + * @param string $str + * @param int|null $default = null + * + * @param \Closure|null $filter + * + * @return int|null + */ + public static function toInt(string $str, int $default = null, \Closure $filter = null) : ?int{ + if(is_numeric($str)){ + $i = (int) $str; + }elseif(is_numeric($default)){ + $i = $default; + }else{ + return null; + } + if(!$filter){ + return $i; + }elseif($result = $filter($i)){ + return $result === -1 ? $default : $i; + }else{ + return null; + } + } + + /** + * @param string $str + * @param string $end + * + * @return bool + */ + public static function endsWith(string $str, string $end) : bool{ + $strlen = strlen($str); + $endlen = strlen($end); + if($endlen > $strlen){ + return false; + } + return substr_compare($str, $end, $strlen - $endlen, $endlen) === 0; + } +} \ No newline at end of file diff --git a/src/presentkim/humanoid/HumanoidMain.php b/src/presentkim/humanoid/HumanoidMain.php deleted file mode 100644 index 9d252aa..0000000 --- a/src/presentkim/humanoid/HumanoidMain.php +++ /dev/null @@ -1,93 +0,0 @@ -getServer()->getLoader()->loadClass('presentkim\humanoid\util\Utils'); - Translation::loadFromResource($this->getResource('lang/eng.yml'), true); - - Entity::registerEntity(Humanoid::class, true, [ - 'Humanoid', - 'presentkim:humanoid', - ]); - } - } - - public function onEnable() : void{ - $this->load(); - $this->getServer()->getPluginManager()->registerEvents(new DataPacketEventListener(), $this); - $this->getServer()->getPluginManager()->registerEvents(new PlayerEventListener(), $this); - } - - public function load() : void{ - $dataFolder = $this->getDataFolder(); - if (!file_exists($dataFolder)) { - mkdir($dataFolder, 0777, true); - } - $langfilename = $dataFolder . 'lang.yml'; - if (!file_exists($langfilename)) { - $resource = $this->getResource('lang/eng.yml'); - fwrite($fp = fopen("{$dataFolder}lang.yml", "wb"), $contents = stream_get_contents($resource)); - fclose($fp); - Translation::loadFromContents($contents); - } else { - Translation::load($langfilename); - } - - self::$prefix = Translation::translate('prefix'); - $this->reloadCommand(); - - foreach (SetSubCommand::getSubCommands() as $key => $value) { - $value->updateTranslation(); - } - } - - public function reloadCommand() : void{ - if ($this->command == null) { - $this->command = new PoolCommand($this, 'humanoid'); - $this->command->createSubCommand(AddSubCommand::class); - $this->command->createSubCommand(SetSubCommand::class); - $this->command->createSubCommand(RemoveSubCommand::class); - $this->command->createSubCommand(CopySubCommand::class); - $this->command->createSubCommand(CancelSubCommand::class); - $this->command->createSubCommand(LangSubCommand::class); - $this->command->createSubCommand(ReloadSubCommand::class); - } - $this->command->updateTranslation(); - $this->command->updateSudCommandTranslation(); - if ($this->command->isRegistered()) { - $this->getServer()->getCommandMap()->unregister($this->command); - } - $this->getServer()->getCommandMap()->register(strtolower($this->getName()), $this->command); - } -} diff --git a/src/presentkim/humanoid/act/ClickHumanoidAct.php b/src/presentkim/humanoid/act/ClickHumanoidAct.php deleted file mode 100644 index 5788eda..0000000 --- a/src/presentkim/humanoid/act/ClickHumanoidAct.php +++ /dev/null @@ -1,11 +0,0 @@ -getLowerCaseName()] ?? null; - } - - /** @param PlayerAct $task */ - public static function registerAct(PlayerAct $task) : void{ - PlayerAct::$acts[$task->getKey()] = $task; - } - - /** @param PlayerAct $task */ - public static function cancelAct(PlayerAct $task) : void{ - unset(PlayerAct::$acts[$task->getKey()]); - } - - public static function cancelAllAct() : void{ - PlayerAct::$acts = []; - } - - /** @var Player */ - protected $player; - - /** @var int */ - protected $id; - - /** @param \pocketmine\Player $player */ - public function __construct(Player $player){ - $this->player = $player; - } - - public function register() : void{ - self::registerAct($this); - } - - public function cancel() : void{ - self::cancelAct($this); - } - - /** @return string */ - public function getKey() : string{ - return $this->player->getLowerCaseName(); - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/PoolCommand.php b/src/presentkim/humanoid/command/PoolCommand.php deleted file mode 100644 index e1405d8..0000000 --- a/src/presentkim/humanoid/command/PoolCommand.php +++ /dev/null @@ -1,96 +0,0 @@ -setExecutor($this); - - $reflection = new \ReflectionClass(Command::class); - $this->property = $reflection->getProperty('name'); - $this->property->setAccessible(true); - - $this->uname = $name; - $this->setPermission("{$name}.cmd"); - $this->updateTranslation(); - - $this->subCommands = $subCommands; - } - - /** - * @param CommandSender $sender - * @param Command $command - * @param string $label - * @param string[] $args - * - * @return bool - */ - public function onCommand(CommandSender $sender, Command $command, string $label, array $args) : bool{ - if (!isset($args[0])) { - return false; - } else { - $label = array_shift($args); - foreach ($this->subCommands as $key => $value) { - if ($value->checkLabel($label)) { - $value->execute($sender, $args); - return true; - } - } - return false; - } - } - - /** @return SubCommand[] */ - public function getSubCommands() : array{ - return $this->subCommands; - } - - /** @param SubCommand[] $subCommands */ - public function setSubCommands(SubCommand ...$subCommands) : void{ - $this->subCommands = $subCommands; - } - - /** @param SubCommand::class $subCommandClass */ - public function createSubCommand($subCommandClass) : void{ - $this->subCommands[] = new $subCommandClass($this); - } - - public function updateTranslation() : void{ - $this->property->setValue($this, Translation::translate("command-{$this->uname}")); - $this->description = Translation::translate("command-{$this->uname}@description"); - $this->usageMessage = Translation::translate("command-{$this->uname}@usage"); - $aliases = Translation::getArray("command-{$this->uname}@aliases"); - if (is_array($aliases)) { - $this->setAliases($aliases); - } - } - - public function updateSudCommandTranslation() : void{ - foreach ($this->subCommands as $key => $value) { - $value->updateTranslation(); - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/SimpleSubCommand.php b/src/presentkim/humanoid/command/SimpleSubCommand.php deleted file mode 100644 index 678f652..0000000 --- a/src/presentkim/humanoid/command/SimpleSubCommand.php +++ /dev/null @@ -1,88 +0,0 @@ -uname = $uname; - - $this->updateTranslation(); - } - - /** - * @param CommandSender $sender - * @param String[] $args - * - * @return bool - */ - abstract public function onCommand(CommandSender $sender, array $args) : bool; - - /** - * @param string $label - * - * @return bool - */ - public function checkLabel(string $label) : bool{ - return strcasecmp($label, $this->label) === 0 || $this->aliases && in_arrayi($label, $this->aliases); - } - - /** @return string */ - public function getLabel() : string{ - return $this->label; - } - - /** @param string $label */ - public function setLabel(string $label) : void{ - $this->label = $label; - } - - /** @return string[] */ - public function getAliases() : array{ - return $this->aliases; - } - - /** @param string[] $aliases */ - public function setAliases(array $aliases) : void{ - $this->aliases = $aliases; - } - - /** @return string */ - public function getUsage() : string{ - return $this->usage; - } - - /** @param string $usage */ - public function setUsage(string $usage) : void{ - $this->usage = $usage; - } - - public function updateTranslation() : void{ - $this->label = Translation::translate("command-humanoid-set-{$this->uname}"); - $this->aliases = Translation::getArray("command-humanoid-set-{$this->uname}@aliases"); - $this->usage = Translation::translate("command-humanoid-set-{$this->uname}@usage"); - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/SubCommand.php b/src/presentkim/humanoid/command/SubCommand.php deleted file mode 100644 index 7fc2e20..0000000 --- a/src/presentkim/humanoid/command/SubCommand.php +++ /dev/null @@ -1,108 +0,0 @@ -owner = $owner; - $this->plugin = $owner->getPlugin(); - - $this->strId = "command-{$owner->uname}-{$label}"; - $this->permission = "{$owner->uname}.cmd.{$label}"; - - $this->updateTranslation(); - } - - /** - * @param CommandSender $sender - * @param String[] $args - */ - public function execute(CommandSender $sender, array $args) : void{ - if (!$this->checkPermission($sender)) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@permission')); - } elseif (!$this->onCommand($sender, $args)) { - $sender->sendMessage(Plugin::$prefix . $this->usage); - } - } - - /** - * @param CommandSender $sender - * @param String[] $args - * - * @return bool - */ - abstract public function onCommand(CommandSender $sender, array $args) : bool; - - /** - * @param CommandSender $target - * - * @return bool - */ - public function checkPermission(CommandSender $target) : bool{ - if ($this->permission === null) { - return true; - } else { - return $target->hasPermission($this->permission); - } - } - - /** - * @param string $tag - * @param string[] $params - * - * @return string - */ - public function translate(string $tag, string ...$params) : string{ - return Translation::translate("{$this->strId}@{$tag}", ...$params); - } - - /** - * @param string $label - * - * @return bool - */ - public function checkLabel(string $label) : bool{ - return strcasecmp($label, $this->label) === 0 || $this->aliases && in_arrayi($label, $this->aliases); - } - - public function updateTranslation() : void{ - $this->label = Translation::translate($this->strId); - $this->aliases = Translation::getArray("{$this->strId}@aliases"); - $this->usage = $this->translate('usage'); - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/AddSubCommand.php b/src/presentkim/humanoid/command/subcommands/AddSubCommand.php deleted file mode 100644 index 074384c..0000000 --- a/src/presentkim/humanoid/command/subcommands/AddSubCommand.php +++ /dev/null @@ -1,75 +0,0 @@ -getNameTag()) extends PlayerAct implements InteractAct{ - - /** @var string */ - private $name; - - /** - * @param Player $player - * @param string $name - */ - public function __construct(Player $player, string $name){ - parent::__construct($player); - $this->name = $name; - } - - /** @param PlayerInteractEvent $event */ - public function onInteract(PlayerInteractEvent $event) : void{ - if ($event->getAction() === PlayerInteractEvent::RIGHT_CLICK_AIR) { - $nbt = Entity::createBaseNBT($this->player, null, $this->player->yaw, $this->player->pitch); - } else { - $nbt = Entity::createBaseNBT($event->getBlock()->add(0.5, 1, 0.5)); - $nbt->setTag($this->player->getInventory()->getItemInHand()->nbtSerialize(-1, 'HeldItem')); - } - $skin = $this->player->getSkin(); - $nbt->setString('SkinData', $skin->getSkinData()); - $nbt->setString('GeometryName', $skin->getGeometryName()); - $nbt->setString('CustomName', $this->name); - - $entity = Entity::createEntity('Humanoid', $this->player->level, $nbt); - $entity->spawnToAll(); - - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-add@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - } - return true; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/CancelSubCommand.php b/src/presentkim/humanoid/command/subcommands/CancelSubCommand.php deleted file mode 100644 index 8b19154..0000000 --- a/src/presentkim/humanoid/command/subcommands/CancelSubCommand.php +++ /dev/null @@ -1,41 +0,0 @@ -cancel(); - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - } else { - $sender->sendMessage(Plugin::$prefix . $this->translate('failure')); - } - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - } - return true; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/CopySubCommand.php b/src/presentkim/humanoid/command/subcommands/CopySubCommand.php deleted file mode 100644 index f6914bc..0000000 --- a/src/presentkim/humanoid/command/subcommands/CopySubCommand.php +++ /dev/null @@ -1,86 +0,0 @@ -cancel(); - PlayerAct::registerAct(new class ($this->player, clone $event->getHumanoid()->namedtag) extends PlayerAct implements InteractAct{ - - /** @var CompoundTag */ - private $nbt; - - /** - * @param Player $player - * @param CompoundTag $nbt - */ - public function __construct(Player $player, CompoundTag $nbt){ - parent::__construct($player); - $this->nbt = $nbt; - } - - /** @param PlayerInteractEvent $event */ - public function onInteract(PlayerInteractEvent $event) : void{ - $pos = $event->getAction() === PlayerInteractEvent::RIGHT_CLICK_AIR ? $this->player->asPosition() : $pos = $event->getBlock(); - $this->nbt->setTag(new ListTag("Pos", [ - new DoubleTag("", $pos->x), - new DoubleTag("", $pos->y), - new DoubleTag("", $pos->z), - ])); - - $entity = Entity::createEntity('Humanoid', $pos->level, $this->nbt); - $entity->spawnToAll(); - - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-copy@success-paste')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-copy@success-copy')); - - $event->setCancelled(true); - } - }); - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - } - return true; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/LangSubCommand.php b/src/presentkim/humanoid/command/subcommands/LangSubCommand.php deleted file mode 100644 index 80c85fd..0000000 --- a/src/presentkim/humanoid/command/subcommands/LangSubCommand.php +++ /dev/null @@ -1,48 +0,0 @@ -plugin->getResource("lang/$args[0].yml"); - if (is_resource($resource)) { - $dataFolder = $this->plugin->getDataFolder(); - if (!file_exists($dataFolder)) { - mkdir($dataFolder, 0777, true); - } - - fwrite($fp = fopen("{$dataFolder}lang.yml", "wb"), $contents = stream_get_contents($resource)); - fclose($fp); - Translation::loadFromContents($contents); - $this->plugin->reloadCommand(); - - $sender->sendMessage(Plugin::$prefix . $this->translate('success', $args[0])); - } else { - $sender->sendMessage(Plugin::$prefix . $this->translate('failure', $args[0])); - } - return true; - } else { - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/ReloadSubCommand.php b/src/presentkim/humanoid/command/subcommands/ReloadSubCommand.php deleted file mode 100644 index 538d5e3..0000000 --- a/src/presentkim/humanoid/command/subcommands/ReloadSubCommand.php +++ /dev/null @@ -1,30 +0,0 @@ -plugin->load(); - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - - return true; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/RemoveSubCommand.php b/src/presentkim/humanoid/command/subcommands/RemoveSubCommand.php deleted file mode 100644 index 17fb918..0000000 --- a/src/presentkim/humanoid/command/subcommands/RemoveSubCommand.php +++ /dev/null @@ -1,50 +0,0 @@ -getHumanoid()->kill(); - - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-remove@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - } - return true; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/SetSubCommand.php b/src/presentkim/humanoid/command/subcommands/SetSubCommand.php deleted file mode 100644 index 8ff9538..0000000 --- a/src/presentkim/humanoid/command/subcommands/SetSubCommand.php +++ /dev/null @@ -1,70 +0,0 @@ - $value) { - if ($value->checkLabel($label)) { - if ($value->onCommand($sender, $args)) { - $sender->sendMessage(Plugin::$prefix . $this->translate('success')); - } - return true; - } - } - $sender->sendMessage(Plugin::$prefix . $this->translate('failure', $label)); - return true; - } - return false; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetGeometryCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetGeometryCommand.php deleted file mode 100644 index d3e02dc..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetGeometryCommand.php +++ /dev/null @@ -1,68 +0,0 @@ -getSkin()->getGeometryName(); - } - PlayerAct::registerAct(new class($sender, implode('_', $args)) extends PlayerAct implements ClickHumanoidAct{ - - /** @var string */ - private $geometryName; - - /** - * @param Player $player - * @param string $geometryName - */ - public function __construct(Player $player, string $geometryName){ - parent::__construct($player); - $this->geometryName = $geometryName; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->setSkin(new Skin('humanoid', $event->getHumanoid()->getSkin()->getSkinData(), '', $this->geometryName)); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-geometry@success', $this->geometryName)); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetItemCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetItemCommand.php deleted file mode 100644 index 64fa916..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetItemCommand.php +++ /dev/null @@ -1,84 +0,0 @@ -getInventory()->getItemInHand(); - } else { - $id = toInt($args[0], null, function (int $i){ - return $i >= 0; - }); - $damage = isset($args[1]) ? toInt($args[1], 0, function (int $i){ - return $i >= 0; - }) : 0; - if ($id === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); - return false; - } else { - $item = Item::get($id, $damage); - - } - } - PlayerAct::registerAct(new class ($sender, $item) extends PlayerAct implements ClickHumanoidAct{ - - /** @var Item | null */ - private $item; - - /** - * @param Player $player - * @param Item|null $item - */ - public function __construct(Player $player, Item $item = null){ - parent::__construct($player); - $this->item = $item; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->setHeldItem($this->item); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-item@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetNameCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetNameCommand.php deleted file mode 100644 index 6bd7008..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetNameCommand.php +++ /dev/null @@ -1,64 +0,0 @@ -name = $name; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->setNameTag($this->name); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-name@success', $this->name)); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetPositionCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetPositionCommand.php deleted file mode 100644 index cce8a28..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetPositionCommand.php +++ /dev/null @@ -1,106 +0,0 @@ -asPosition(); - } elseif (isset($args[0]) && !isset($args[1])) { - if ($args === '*') { - $pos = $sender->asPosition(); - } else { - $player = Server::getInstance()->getPlayerExact($args[0]); - if ($player === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-player', $args[0])); - return false; - } else { - $pos = $player->asPosition(); - } - } - } elseif (isset($args[2])) { - $x = is_numeric($args[0]) ? (float) $args[0] : null; - if ($x === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); - return false; - } - $y = is_numeric($args[1]) ? (float) $args[1] : null; - if ($y === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[1])); - return false; - } - $z = is_numeric($args[2]) ? (float) $args[2] : null; - if ($z === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[2])); - return false; - } - if (isset($args[3])) { - $level = Server::getInstance()->getLevelByName($args[3]); - if ($level === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[3])); - return false; - } - } else { - $level = $sender->getLevel(); - } - $pos = new Position($x, $y, $z, $level); - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - PlayerAct::registerAct(new class($sender, $pos) extends PlayerAct implements ClickHumanoidAct{ - - /** @var Vector3 */ - private $pos; - - /** - * @param Player $player - * @param Vector3 $pos - */ - public function __construct(Player $player, Vector3 $pos){ - parent::__construct($player); - $this->pos = $pos; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->teleport($this->pos); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-position@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetRotationCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetRotationCommand.php deleted file mode 100644 index 22dfb60..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetRotationCommand.php +++ /dev/null @@ -1,88 +0,0 @@ -yaw; - $pitch = $sender->pitch; - } elseif (isset($args[1])) { - $yaw = is_numeric($args[0]) ? (float) $args[0] : null; - $pitch = is_numeric($args[1]) ? (float) $args[1] : null; - if ($yaw === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); - return false; - } elseif ($pitch === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[1])); - return false; - } - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - PlayerAct::registerAct(new class($sender, $yaw, $pitch) extends PlayerAct implements ClickHumanoidAct{ - - /** @var int | null */ - private $yaw; - - /** @var int | null */ - private $pitch; - - /** - * @param Player $player - * @param int|null $yaw - * @param int|null $pitch - */ - public function __construct(Player $player, ?int $yaw = null, ?int $pitch = null){ - parent::__construct($player); - $this->yaw = $yaw; - $this->pitch = $pitch; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $this->yaw = $this->yaw ?? $this->player->yaw; - $this->pitch = $this->pitch ?? $this->player->pitch; - $event->getHumanoid()->setRotation($this->yaw, $this->pitch); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-rotation@success', $this->yaw, $this->pitch)); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetScaleCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetScaleCommand.php deleted file mode 100644 index 93a9dd4..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetScaleCommand.php +++ /dev/null @@ -1,75 +0,0 @@ -= 10; - }); - if ($scale === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid', $args[0])); - return false; - } else { - PlayerAct::registerAct(new class($sender, $scale) extends PlayerAct implements ClickHumanoidAct{ - - /** @var int */ - private $scale; - - /** - * @param Player $player - * @param int $scale - */ - public function __construct(Player $player, int $scale){ - parent::__construct($player); - $this->scale = $scale; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->setScale($this->scale * 0.01); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-scale@success', $this->scale)); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } - } else { - $sender->sendMessage(Plugin::$prefix . $this->usage); - return false; - } - } else { - - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetSkinCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetSkinCommand.php deleted file mode 100644 index ee034da..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetSkinCommand.php +++ /dev/null @@ -1,76 +0,0 @@ -getSkin(); - } else { - $player = Server::getInstance()->getPlayerExact($args[0]); - if ($player === null) { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@invalid-player', $args[0])); - return false; - } else { - $skin = $player->getSkin(); - } - } - } else { - $skin = $sender->getSkin(); - } - PlayerAct::registerAct(new class ($sender, $skin) extends PlayerAct implements ClickHumanoidAct{ - - /** @var Skin | null */ - private $skin; - - /** - * @param Player $player - * @param Skin|null $skin - */ - public function __construct(Player $player, Skin $skin = null){ - parent::__construct($player); - $this->skin = $skin; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $event->getHumanoid()->setSkin($this->skin); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-skin@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/SetSneakCommand.php b/src/presentkim/humanoid/command/subcommands/simple/SetSneakCommand.php deleted file mode 100644 index 1f0affd..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/SetSneakCommand.php +++ /dev/null @@ -1,60 +0,0 @@ -name = $name; - } - - /** @param PlayerClickHumanoidEvent $event */ - public function onClickHumanoid(PlayerClickHumanoidEvent $event) : void{ - $humanoid = $event->getHumanoid(); - $humanoid->setSneaking(!$humanoid->isSneaking()); - $this->player->sendMessage(Plugin::$prefix . Translation::translate('humanoid-set-sneak@success')); - - $event->setCancelled(true); - $this->cancel(); - } - }); - return true; - } else { - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-generic-failure@in-game')); - return false; - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/command/subcommands/simple/ShowListCommand.php b/src/presentkim/humanoid/command/subcommands/simple/ShowListCommand.php deleted file mode 100644 index 98c142b..0000000 --- a/src/presentkim/humanoid/command/subcommands/simple/ShowListCommand.php +++ /dev/null @@ -1,45 +0,0 @@ - $value) { - $list[] = [ - $value->getLabel(), - $value->getUsage(), - ]; - } - - $max = ceil(count($list) / 5); - $page = min($max, (isset($args[0]) ? toInt($args[0], 1, function (int $i){ - return $i > 0 ? 1 : -1; - }) : 1) - 1); - $sender->sendMessage(Plugin::$prefix . Translation::translate('command-humanoid-set-list@head', $page + 1, $max)); - for ($i = $page * 5; $i < ($page + 1) * 5 && $i < count($list); $i++) { - $sender->sendMessage(Translation::translate('command-humanoid-set-list@item', ...$list[$i])); - } - return false; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/entity/Humanoid.php b/src/presentkim/humanoid/entity/Humanoid.php deleted file mode 100644 index 1eb1242..0000000 --- a/src/presentkim/humanoid/entity/Humanoid.php +++ /dev/null @@ -1,182 +0,0 @@ -uuid = UUID::fromRandom(); - - $this->setHeldItem($this->namedtag->hasTag('HeldItem') ? Item::nbtDeserialize($this->namedtag->getCompoundTag('HeldItem')) : Item::get(Item::AIR)); - - $skinData = $this->namedtag->hasTag('SkinData') ? $this->namedtag->getString('SkinData') : str_repeat("\x00", 8192); - $geometryName = $this->namedtag->hasTag('GeometryName') ? $this->namedtag->getString('GeometryName') : ''; - $geometryData = class_exists(GeometryAPI::class) ? GeometryAPI::getInstance()->getGeometryData($geometryName) ?? '' : ''; - $this->setSkin(new Skin('humanoid', $skinData, '', $geometryName, $geometryData)); - - $this->setSneaking($this->namedtag->hasTag('Sneak') ? (bool) $this->namedtag->getByte('Sneak') : false); - $this->setScale($this->namedtag->hasTag('Scale') ? $this->namedtag->getFloat('Scale') : 1); - } - - /** @return UUID */ - public function getUniqueId() : UUID{ - return $this->uuid; - } - - /** @return Item */ - public function getHeldItem() : Item{ - return clone $this->heldItem; - } - - /** @param Item $heldItem */ - public function setHeldItem(Item $heldItem) : void{ - $this->heldItem = $heldItem; - - $pk = new MobEquipmentPacket(); - $pk->entityRuntimeId = $this->id; - $pk->item = $heldItem; - $pk->inventorySlot = $pk->hotbarSlot = 0; - $pk->windowId = ContainerIds::INVENTORY; - $this->server->broadcastPacket($this->getViewers(), $pk); - } - - /** @return Skin */ - public function getSkin() : Skin{ - return $this->skin; - } - - /** @param Skin $skin */ - public function setSkin(Skin $skin) : void{ - if (!$skin->isValid()) { - throw new \InvalidStateException('Specified skin is not valid, must be 8KiB or 16KiB'); - } - - $this->skin = $skin; - $this->skin->debloatGeometryData(); - $this->sendSkin($this->getViewers()); - } - - /** @param Player[] | null $targets */ - public function sendSkin(array $targets = null) : void{ - $pk = new PlayerSkinPacket(); - $pk->uuid = $this->getUniqueId(); - $pk->skin = $this->skin; - $this->server->broadcastPacket($targets ?? $this->hasSpawned, $pk); - } - - public function saveNBT() : void{ - parent::saveNBT(); - - $this->namedtag->setTag($this->heldItem->nbtSerialize(-1, 'HeldItem')); - $this->namedtag->setTag(new StringTag('SkinData', $this->skin->getSkinData())); - $this->namedtag->setTag(new StringTag('GeometryName', $this->skin->getGeometryName())); - - $this->namedtag->setTag(new ByteTag('Sneak', (int) $this->isSneaking())); - $this->namedtag->setTag(new FloatTag('Scale', $this->getScale())); - } - - /** @param \pocketmine\Player $player */ - protected function sendSpawnPacket(Player $player) : void{ - if (!$this->skin->isValid()) { - throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . ' must have a valid skin set'); - } - - $pk = new AddPlayerPacket(); - $pk->uuid = $this->getUniqueId(); - $pk->username = $this->getNameTag(); - $pk->entityRuntimeId = $this->id; - $pk->position = $this->asVector3(); - $pk->motion = null; - $pk->yaw = $this->yaw; - $pk->pitch = $this->pitch; - $pk->item = $this->heldItem; - $pk->metadata = $this->propertyManager->getAll(); - $player->dataPacket($pk); - - $this->sendSkin([$player]); - } - - /** @param EntityDamageEvent $source */ - public function attack(EntityDamageEvent $source) : void{ - $source->setCancelled(true); - } - - /** - * @param float $dx - * @param float $dy - * @param float $dz - * - * @return bool - */ - public function move(float $dx, float $dy, float $dz) : bool{ - return false; - } - - /** - * @param Vector3 $pos - * @param float|null $yaw - * @param float|null $pitch - * - * @return bool - */ - public function teleport(Vector3 $pos, float $yaw = null, float $pitch = null) : bool{ - if (parent::teleport($pos, $yaw, $pitch)) { - $yaw = $yaw ?? $this->yaw; - $pitch = $pitch ?? $this->pitch; - - $pk = new MovePlayerPacket(); - $pk->entityRuntimeId = $this->getId(); - $pk->position = $this->getOffsetPosition($pos); - $pk->pitch = $pitch; - $pk->headYaw = $yaw; - $pk->yaw = $yaw; - $pk->mode = MovePlayerPacket::MODE_TELEPORT; - - $this->server->broadcastPacket($targets ?? $this->hasSpawned, $pk); - $this->spawnToAll(); - return true; - } - return false; - } -} diff --git a/src/presentkim/humanoid/event/PlayerClickHumanoidEvent.php b/src/presentkim/humanoid/event/PlayerClickHumanoidEvent.php deleted file mode 100644 index 729ada0..0000000 --- a/src/presentkim/humanoid/event/PlayerClickHumanoidEvent.php +++ /dev/null @@ -1,41 +0,0 @@ -player = $player; - $this->humanoid = $humanoid; - $this->action = $action; - } - - /** @return Humanoid */ - public function getHumanoid() : Humanoid{ - return $this->humanoid; - } - - /** @return int */ - public function getAction() : int{ - return $this->action; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/listener/DataPacketEventListener.php b/src/presentkim/humanoid/listener/DataPacketEventListener.php deleted file mode 100644 index 32b0097..0000000 --- a/src/presentkim/humanoid/listener/DataPacketEventListener.php +++ /dev/null @@ -1,37 +0,0 @@ -owner = Plugin::getInstance(); - } - - /** @param DataPacketReceiveEvent $event */ - public function onDataPacketReceiveEvent(DataPacketReceiveEvent $event) : void{ - $pk = $event->getPacket(); - if ($pk instanceof InventoryTransactionPacket) { - if ($pk->transactionType === InventoryTransactionPacket::TYPE_USE_ITEM_ON_ENTITY) { - $player = $event->getPlayer(); - $target = $player->level->getEntity($pk->trData->entityRuntimeId); - if ($target instanceof Humanoid) { - $event->setCancelled(true); - Server::getInstance()->getPluginManager()->callEvent(new PlayerClickHumanoidEvent($player, $target, $pk->trData->actionType)); - } - } - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/listener/PlayerEventListener.php b/src/presentkim/humanoid/listener/PlayerEventListener.php deleted file mode 100644 index 7e30fac..0000000 --- a/src/presentkim/humanoid/listener/PlayerEventListener.php +++ /dev/null @@ -1,50 +0,0 @@ -owner = Plugin::getInstance(); - } - - /** - * @priority LOW - * - * @param PlayerClickHumanoidEvent $event - */ - public function onPlayerClickHumanoidEvent(PlayerClickHumanoidEvent $event) : void{ - if (!$event->isCancelled()) { - $task = PlayerAct::getAct($player = $event->getPlayer()); - if ($task instanceof ClickHumanoidAct) { - $task->onClickHumanoid($event); - } - } - } - - /** - * @priority LOW - * - * @param PlayerInteractEvent $event - */ - public function onPlayerInteractEvent(PlayerInteractEvent $event) : void{ - if (!$event->isCancelled()) { - $task = PlayerAct::getAct($player = $event->getPlayer()); - if ($task instanceof InteractAct) { - $task->onInteract($event); - } - } - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/util/Translation.php b/src/presentkim/humanoid/util/Translation.php deleted file mode 100644 index 0a30782..0000000 --- a/src/presentkim/humanoid/util/Translation.php +++ /dev/null @@ -1,91 +0,0 @@ -getLogger()->debug("get $strId from default"); - $value = self::$default[$strId]; - } else { - Plugin::getInstance()->getLogger()->critical("get $strId failed"); - return "Undefined strId : $strId"; - } - - if (is_array($value)) { - $value = $value[array_rand($value)]; - } - if (is_string($value)) { - return empty($params) ? $value : strtr($value, listToPairs($params)); - } else { - return "$strId is not string"; - } - } - - /** - * @param string $strId - * - * @return string[] | null - */ - public static function getArray(string $strId) : ?array{ - if (isset(self::$lang[$strId])) { - $value = self::$lang[$strId]; - } elseif (isset(self::$default[$strId])) { - Plugin::getInstance()->getLogger()->debug("get $strId from default"); - $value = self::$default[$strId]; - } else { - Plugin::getInstance()->getLogger()->critical("get $strId failed"); - return null; - } - return is_array($value) ? $value : null; - } -} \ No newline at end of file diff --git a/src/presentkim/humanoid/util/Utils.php b/src/presentkim/humanoid/util/Utils.php deleted file mode 100644 index c8987d4..0000000 --- a/src/presentkim/humanoid/util/Utils.php +++ /dev/null @@ -1,57 +0,0 @@ - $value) { - if (strcasecmp($str, $value) === 0) { - return true; - } - } - return false; -} - -/** - * @param Object[] $list - * - * @return string[] - */ -function listToPairs(array $list) : array{ - $pairs = []; - $size = sizeOf($list); - for ($i = 0; $i < $size; ++$i) { - $pairs["{%$i}"] = $list[$i]; - } - return $pairs; -} - -/** - * @param string $str - * @param int|null $default = null - * - * @param \Closure|null $filter - * - * @return int|null - */ -function toInt(string $str, int $default = null, \Closure $filter = null) : ?int{ - if (is_numeric($str)) { - $i = (int) $str; - } elseif (is_numeric($default)) { - $i = $default; - } else { - return null; - } - if (!$filter) { - return $i; - } elseif ($result = $filter($i)) { - return $result === -1 ? $default : $i; - } else { - return null; - } -} \ No newline at end of file