├── .gitignore ├── .travis.yml ├── LICENSE ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── readme.md └── src └── main ├── java └── com │ └── github │ └── noonmaru │ └── customentity │ ├── CustomEntityPacket.java │ ├── CustomEntityPlugin.java │ ├── FakeStand.java │ ├── FakeStandManager.java │ ├── cmd │ ├── CommandCE.java │ ├── CommandCEColor.java │ ├── CommandCEColorAndScale.java │ ├── CommandCERegister.java │ ├── CommandCEScale.java │ └── CommandCEUnregister.java │ └── util │ └── PacketBuilder.java └── resources └── plugin.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | build/ 4 | *.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: true 3 | jdk: 4 | - openjdk8 5 | 6 | branches: 7 | only: 8 | - master 9 | - develop 10 | 11 | before_install: 12 | - chmod +x ./gradlew 13 | 14 | cache: 15 | directories: 16 | - '$HOME/.m2' 17 | - '$HOME/.gradle' -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The GNU General Public License (GPL) 2 | 3 | Version 2, June 1991 4 | 5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 6 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this license 9 | document, but changing it is not allowed. 10 | 11 | Preamble 12 | 13 | The licenses for most software are designed to take away your freedom to share 14 | and change it. By contrast, the GNU General Public License is intended to 15 | guarantee your freedom to share and change free software--to make sure the 16 | software is free for all its users. This General Public License applies to 17 | most of the Free Software Foundation's software and to any other program whose 18 | authors commit to using it. (Some other Free Software Foundation software is 19 | covered by the GNU Library General Public License instead.) You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not price. Our 23 | General Public Licenses are designed to make sure that you have the freedom to 24 | distribute copies of free software (and charge for this service if you wish), 25 | that you receive source code or can get it if you want it, that you can change 26 | the software or use pieces of it in new free programs; and that you know you 27 | can do these things. 28 | 29 | To protect your rights, we need to make restrictions that forbid anyone to deny 30 | you these rights or to ask you to surrender the rights. These restrictions 31 | translate to certain responsibilities for you if you distribute copies of the 32 | software, or if you modify it. 33 | 34 | For example, if you distribute copies of such a program, whether gratis or for 35 | a fee, you must give the recipients all the rights that you have. You must 36 | make sure that they, too, receive or can get the source code. And you must 37 | show them these terms so they know their rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and (2) 40 | offer you this license which gives you legal permission to copy, distribute 41 | and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain that 44 | everyone understands that there is no warranty for this free software. If the 45 | software is modified by someone else and passed on, we want its recipients to 46 | know that what they have is not the original, so that any problems introduced 47 | by others will not reflect on the original authors' reputations. 48 | 49 | Finally, any free program is threatened constantly by software patents. We 50 | wish to avoid the danger that redistributors of a free program will 51 | individually obtain patent licenses, in effect making the program proprietary. 52 | To prevent this, we have made it clear that any patent must be licensed for 53 | everyone's free use or not licensed at all. 54 | 55 | The precise terms and conditions for copying, distribution and modification 56 | follow. 57 | 58 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 59 | 60 | 0. This License applies to any program or other work which contains a notice 61 | placed by the copyright holder saying it may be distributed under the terms of 62 | this General Public License. The "Program", below, refers to any such program 63 | or work, and a "work based on the Program" means either the Program or any 64 | derivative work under copyright law: that is to say, a work containing the 65 | Program or a portion of it, either verbatim or with modifications and/or 66 | translated into another language. (Hereinafter, translation is included 67 | without limitation in the term "modification".) Each licensee is addressed as 68 | "you". 69 | 70 | Activities other than copying, distribution and modification are not covered by 71 | this License; they are outside its scope. The act of running the Program is 72 | not restricted, and the output from the Program is covered only if its contents 73 | constitute a work based on the Program (independent of having been made by 74 | running the Program). Whether that is true depends on what the Program does. 75 | 76 | 1. You may copy and distribute verbatim copies of the Program's source code as 77 | you receive it, in any medium, provided that you conspicuously and 78 | appropriately publish on each copy an appropriate copyright notice and 79 | disclaimer of warranty; keep intact all the notices that refer to this License 80 | and to the absence of any warranty; and give any other recipients of the 81 | Program a copy of this License along with the Program. 82 | 83 | You may charge a fee for the physical act of transferring a copy, and you may 84 | at your option offer warranty protection in exchange for a fee. 85 | 86 | 2. You may modify your copy or copies of the Program or any portion of it, thus 87 | forming a work based on the Program, and copy and distribute such modifications 88 | or work under the terms of Section 1 above, provided that you also meet all of 89 | these conditions: 90 | 91 | a) You must cause the modified files to carry prominent notices stating 92 | that you changed the files and the date of any change. 93 | 94 | b) You must cause any work that you distribute or publish, that in whole or 95 | in part contains or is derived from the Program or any part thereof, to be 96 | licensed as a whole at no charge to all third parties under the terms of 97 | this License. 98 | 99 | c) If the modified program normally reads commands interactively when run, 100 | you must cause it, when started running for such interactive use in the 101 | most ordinary way, to print or display an announcement including an 102 | appropriate copyright notice and a notice that there is no warranty (or 103 | else, saying that you provide a warranty) and that users may redistribute 104 | the program under these conditions, and telling the user how to view a copy 105 | of this License. (Exception: if the Program itself is interactive but does 106 | not normally print such an announcement, your work based on the Program is 107 | not required to print an announcement.) 108 | 109 | These requirements apply to the modified work as a whole. If identifiable 110 | sections of that work are not derived from the Program, and can be reasonably 111 | considered independent and separate works in themselves, then this License, and 112 | its terms, do not apply to those sections when you distribute them as separate 113 | works. But when you distribute the same sections as part of a whole which is a 114 | work based on the Program, the distribution of the whole must be on the terms 115 | of this License, whose permissions for other licensees extend to the entire 116 | whole, and thus to each and every part regardless of who wrote it. 117 | 118 | Thus, it is not the intent of this section to claim rights or contest your 119 | rights to work written entirely by you; rather, the intent is to exercise the 120 | right to control the distribution of derivative or collective works based on 121 | the Program. 122 | 123 | In addition, mere aggregation of another work not based on the Program with the 124 | Program (or with a work based on the Program) on a volume of a storage or 125 | distribution medium does not bring the other work under the scope of this 126 | License. 127 | 128 | 3. You may copy and distribute the Program (or a work based on it, under 129 | Section 2) in object code or executable form under the terms of Sections 1 and 130 | 2 above provided that you also do one of the following: 131 | 132 | a) Accompany it with the complete corresponding machine-readable source 133 | code, which must be distributed under the terms of Sections 1 and 2 above 134 | on a medium customarily used for software interchange; or, 135 | 136 | b) Accompany it with a written offer, valid for at least three years, to 137 | give any third party, for a charge no more than your cost of physically 138 | performing source distribution, a complete machine-readable copy of the 139 | corresponding source code, to be distributed under the terms of Sections 1 140 | and 2 above on a medium customarily used for software interchange; or, 141 | 142 | c) Accompany it with the information you received as to the offer to 143 | distribute corresponding source code. (This alternative is allowed only 144 | for noncommercial distribution and only if you received the program in 145 | object code or executable form with such an offer, in accord with 146 | Subsection b above.) 147 | 148 | The source code for a work means the preferred form of the work for making 149 | modifications to it. For an executable work, complete source code means all 150 | the source code for all modules it contains, plus any associated interface 151 | definition files, plus the scripts used to control compilation and installation 152 | of the executable. However, as a special exception, the source code 153 | distributed need not include anything that is normally distributed (in either 154 | source or binary form) with the major components (compiler, kernel, and so on) 155 | of the operating system on which the executable runs, unless that component 156 | itself accompanies the executable. 157 | 158 | If distribution of executable or object code is made by offering access to copy 159 | from a designated place, then offering equivalent access to copy the source 160 | code from the same place counts as distribution of the source code, even though 161 | third parties are not compelled to copy the source along with the object code. 162 | 163 | 4. You may not copy, modify, sublicense, or distribute the Program except as 164 | expressly provided under this License. Any attempt otherwise to copy, modify, 165 | sublicense or distribute the Program is void, and will automatically terminate 166 | your rights under this License. However, parties who have received copies, or 167 | rights, from you under this License will not have their licenses terminated so 168 | long as such parties remain in full compliance. 169 | 170 | 5. You are not required to accept this License, since you have not signed it. 171 | However, nothing else grants you permission to modify or distribute the Program 172 | or its derivative works. These actions are prohibited by law if you do not 173 | accept this License. Therefore, by modifying or distributing the Program (or 174 | any work based on the Program), you indicate your acceptance of this License to 175 | do so, and all its terms and conditions for copying, distributing or modifying 176 | the Program or works based on it. 177 | 178 | 6. Each time you redistribute the Program (or any work based on the Program), 179 | the recipient automatically receives a license from the original licensor to 180 | copy, distribute or modify the Program subject to these terms and conditions. 181 | You may not impose any further restrictions on the recipients' exercise of the 182 | rights granted herein. You are not responsible for enforcing compliance by 183 | third parties to this License. 184 | 185 | 7. If, as a consequence of a court judgment or allegation of patent 186 | infringement or for any other reason (not limited to patent issues), conditions 187 | are imposed on you (whether by court order, agreement or otherwise) that 188 | contradict the conditions of this License, they do not excuse you from the 189 | conditions of this License. If you cannot distribute so as to satisfy 190 | simultaneously your obligations under this License and any other pertinent 191 | obligations, then as a consequence you may not distribute the Program at all. 192 | For example, if a patent license would not permit royalty-free redistribution 193 | of the Program by all those who receive copies directly or indirectly through 194 | you, then the only way you could satisfy both it and this License would be to 195 | refrain entirely from distribution of the Program. 196 | 197 | If any portion of this section is held invalid or unenforceable under any 198 | particular circumstance, the balance of the section is intended to apply and 199 | the section as a whole is intended to apply in other circumstances. 200 | 201 | It is not the purpose of this section to induce you to infringe any patents or 202 | other property right claims or to contest validity of any such claims; this 203 | section has the sole purpose of protecting the integrity of the free software 204 | distribution system, which is implemented by public license practices. Many 205 | people have made generous contributions to the wide range of software 206 | distributed through that system in reliance on consistent application of that 207 | system; it is up to the author/donor to decide if he or she is willing to 208 | distribute software through any other system and a licensee cannot impose that 209 | choice. 210 | 211 | This section is intended to make thoroughly clear what is believed to be a 212 | consequence of the rest of this License. 213 | 214 | 8. If the distribution and/or use of the Program is restricted in certain 215 | countries either by patents or by copyrighted interfaces, the original 216 | copyright holder who places the Program under this License may add an explicit 217 | geographical distribution limitation excluding those countries, so that 218 | distribution is permitted only in or among countries not thus excluded. In 219 | such case, this License incorporates the limitation as if written in the body 220 | of this License. 221 | 222 | 9. The Free Software Foundation may publish revised and/or new versions of the 223 | General Public License from time to time. Such new versions will be similar in 224 | spirit to the present version, but may differ in detail to address new problems 225 | or concerns. 226 | 227 | Each version is given a distinguishing version number. If the Program 228 | specifies a version number of this License which applies to it and "any later 229 | version", you have the option of following the terms and conditions either of 230 | that version or of any later version published by the Free Software Foundation. 231 | If the Program does not specify a version number of this License, you may 232 | choose any version ever published by the Free Software Foundation. 233 | 234 | 10. If you wish to incorporate parts of the Program into other free programs 235 | whose distribution conditions are different, write to the author to ask for 236 | permission. For software which is copyrighted by the Free Software Foundation, 237 | write to the Free Software Foundation; we sometimes make exceptions for this. 238 | Our decision will be guided by the two goals of preserving the free status of 239 | all derivatives of our free software and of promoting the sharing and reuse of 240 | software generally. 241 | 242 | NO WARRANTY 243 | 244 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR 245 | THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE 246 | STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE 247 | PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 248 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 249 | FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 250 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, 251 | YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 252 | 253 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL 254 | ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE 255 | PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 256 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR 257 | INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA 258 | BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 259 | FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER 260 | OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 261 | 262 | END OF TERMS AND CONDITIONS 263 | 264 | How to Apply These Terms to Your New Programs 265 | 266 | If you develop a new program, and you want it to be of the greatest possible 267 | use to the public, the best way to achieve this is to make it free software 268 | which everyone can redistribute and change under these terms. 269 | 270 | To do so, attach the following notices to the program. It is safest to attach 271 | them to the start of each source file to most effectively convey the exclusion 272 | of warranty; and each file should have at least the "copyright" line and a 273 | pointer to where the full notice is found. 274 | 275 | One line to give the program's name and a brief idea of what it does. 276 | 277 | Copyright (C) 278 | 279 | This program is free software; you can redistribute it and/or modify it 280 | under the terms of the GNU General Public License as published by the Free 281 | Software Foundation; either version 2 of the License, or (at your option) 282 | any later version. 283 | 284 | This program is distributed in the hope that it will be useful, but WITHOUT 285 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 286 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 287 | more details. 288 | 289 | You should have received a copy of the GNU General Public License along 290 | with this program; if not, write to the Free Software Foundation, Inc., 291 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 292 | 293 | Also add information on how to contact you by electronic and paper mail. 294 | 295 | If the program is interactive, make it output a short notice like this when it 296 | starts in an interactive mode: 297 | 298 | Gnomovision version 69, Copyright (C) year name of author Gnomovision comes 299 | with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free 300 | software, and you are welcome to redistribute it under certain conditions; 301 | type 'show c' for details. 302 | 303 | The hypothetical commands 'show w' and 'show c' should show the appropriate 304 | parts of the General Public License. Of course, the commands you use may be 305 | called something other than 'show w' and 'show c'; they could even be 306 | mouse-clicks or menu items--whatever suits your program. 307 | 308 | You should also get your employer (if you work as a programmer) or your school, 309 | if any, to sign a "copyright disclaimer" for the program, if necessary. Here 310 | is a sample; alter the names: 311 | 312 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 313 | 'Gnomovision' (which makes passes at compilers) written by James Hacker. 314 | 315 | signature of Ty Coon, 1 April 1989 316 | 317 | Ty Coon, President of Vice 318 | 319 | This General Public License does not permit incorporating your program into 320 | proprietary programs. If your program is a subroutine library, you may 321 | consider it more useful to permit linking proprietary applications with the 322 | library. If this is what you want to do, use the GNU Library General Public 323 | License instead of this License. 324 | 325 | 326 | "CLASSPATH" EXCEPTION TO THE GPL 327 | 328 | Certain source files distributed by Oracle America and/or its affiliates are 329 | subject to the following clarification and special exception to the GPL, but 330 | only where Oracle has expressly included in the particular source file's header 331 | the words "Oracle designates this particular file as subject to the "Classpath" 332 | exception as provided by Oracle in the LICENSE file that accompanied this code." 333 | 334 | Linking this library statically or dynamically with other modules is making 335 | a combined work based on this library. Thus, the terms and conditions of 336 | the GNU General Public License cover the whole combination. 337 | 338 | As a special exception, the copyright holders of this library give you 339 | permission to link this library with independent modules to produce an 340 | executable, regardless of the license terms of these independent modules, 341 | and to copy and distribute the resulting executable under terms of your 342 | choice, provided that you also meet, for each linked independent module, 343 | the terms and conditions of the license of that module. An independent 344 | module is a module which is not derived from or based on this library. If 345 | you modify this library, you may extend this exception to your version of 346 | the library, but you are not obligated to do so. If you do not wish to do 347 | so, delete this exception statement from your version. -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'maven-publish' 4 | } 5 | 6 | group = pluginGroup 7 | version = pluginVersion 8 | 9 | sourceCompatibility = 1.8 10 | targetCompatibility = 1.8 11 | compileJava.options.encoding = 'UTF-8' 12 | javadoc.options.encoding = 'UTF-8' 13 | archivesBaseName = 'custom-entity-bukkit' 14 | 15 | repositories { 16 | mavenCentral() 17 | maven { 18 | name = 'spigotmc-repo' 19 | url = 'https://hub.spigotmc.org/nexus/content/groups/public/' 20 | } 21 | maven { 22 | name = 'sonatype' 23 | url = 'https://oss.sonatype.org/content/groups/public/' 24 | } 25 | maven { 26 | name = 'jitpack' 27 | url = 'https://jitpack.io' 28 | } 29 | } 30 | 31 | dependencies { 32 | testCompile group: 'junit', name: 'junit', version: '4.12' 33 | compile 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT' 34 | compileOnly 'com.github.noonmaru:tap:1.0.1' 35 | } 36 | 37 | import org.apache.tools.ant.filters.ReplaceTokens 38 | 39 | processResources { 40 | from(sourceSets.main.resources.srcDirs) { 41 | filter ReplaceTokens, tokens: [version: version] 42 | } 43 | } 44 | 45 | task sourcesJar(type: Jar) { 46 | classifier = 'sources' 47 | from sourceSets.main.allJava 48 | } 49 | 50 | task javadocJar(type: Jar) { 51 | classifier = 'javadoc' 52 | from javadoc 53 | } 54 | 55 | publishing { 56 | publications { 57 | CustomEntity(MavenPublication) { 58 | from components.java 59 | artifact sourcesJar 60 | artifact javadocJar 61 | pom { 62 | name = 'custom-entity' 63 | description = 'Custom entity spigot plugin' 64 | url = 'https://github.com/noonmaru' 65 | licenses { 66 | license { 67 | name = 'GPL-2.0' 68 | url = 'http://www.opensource.org/licenses/gpl-2.0.php' 69 | } 70 | } 71 | developers { 72 | developer { 73 | id = 'noonmaru' 74 | name = 'Noonmaru' 75 | email = 'noonmaru10@gmail.com' 76 | url = 'https://github.com/noonmaru' 77 | } 78 | } 79 | scm { 80 | connection = 'scm:git:git://bitbucket.org/noonmaru/custom-entity-bukkit.git' 81 | developerConnection = 'scm:git:ssh://bitbucket.org/noonmaru/custom-entity-bukkit.git' 82 | url = 'https://bitbucket.org/noonmaru/custom-entity-bukkit' 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | task spigotJar(type: Copy) { 90 | from jar 91 | into 'W:\\Servers\\test\\plugins' 92 | } 93 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | rootProject.name='custom-entity-bukkit' 2 | pluginGroup=com.github.noonmaru 3 | pluginVersion=1.0.3 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noonmaru/custom-entity-bukkit/9586bd7f8ad549af3c3c2e399f893bbef17ee0ec/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 10 16:02:22 KST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Custom Entity (for bukkit) 2 | 3 | [![Build Status](https://travis-ci.org/noonmaru/custom-entity-bukkit.svg?branch=master)](https://travis-ci.org/noonmaru/custom-entity-bukkit) 4 | [![Maintainability](https://api.codeclimate.com/v1/badges/434a83eb1bcaa2ad9b3f/maintainability)](https://codeclimate.com/github/noonmaru/custom-entity-bukkit/maintainability) 5 | [![](https://jitpack.io/v/noonmaru/custom-entity-bukkit.svg)](https://jitpack.io/#noonmaru/custom-entity-bukkit) 6 | ![JitPack - Downloads](https://img.shields.io/jitpack/dm/github/noonmaru/custom-entity-bukkit) 7 | ![GitHub](https://img.shields.io/github/license/noonmaru/custom-entity-bukkit) 8 | ![Twitch Status](https://img.shields.io/twitch/status/hptgrm) 9 | 10 | > Minecraft Spigot NMS Library 11 | 12 | > * ##### Features 13 | > * Custom Entity Mod server plugin 14 | 15 | > * ##### Gradle 16 | >```groovy 17 | >allprojects { 18 | > repositories { 19 | > ... 20 | > maven { url 'https://jitpack.io' } 21 | > } 22 | >} 23 | > 24 | >... 25 | >dependencies { 26 | > implementation 'com.github.noonmaru:custom-entity:1.0.3' 27 | >} 28 | >``` -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/CustomEntityPacket.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity; 18 | 19 | import com.github.noonmaru.customentity.util.PacketBuilder; 20 | import com.github.noonmaru.tap.packet.Packet; 21 | 22 | 23 | public final class CustomEntityPacket 24 | { 25 | public static final String CHANNEL = "CustomEntity"; 26 | 27 | private static final int REGISTER = 0; 28 | 29 | private static final int UNREGISTER = 1; 30 | 31 | private static final int COLOR = 2; 32 | 33 | private static final int SCALE = 3; 34 | 35 | private static final int COLOR_AND_SCALE = 4; 36 | 37 | private static final int FAKE_ENTITY = 5; 38 | 39 | public static Packet register(int entityId) 40 | { 41 | PacketBuilder builder = PacketBuilder.getInstance(); 42 | 43 | builder.write(REGISTER); 44 | builder.writeInt(entityId); 45 | 46 | return builder.build(); 47 | } 48 | 49 | public static Packet unregister(int... entityIds) 50 | { 51 | PacketBuilder builder = PacketBuilder.getInstance(); 52 | 53 | builder.write(UNREGISTER); 54 | int length = entityIds.length; 55 | builder.writeShort(length); 56 | 57 | for (int i = 0; i < length; i++) 58 | builder.writeInt(entityIds[i]); 59 | 60 | return builder.build(); 61 | } 62 | 63 | public static Packet scale(int entityId, float scaleX, float scaleY, float scaleZ, int duration) 64 | { 65 | PacketBuilder builder = PacketBuilder.getInstance(); 66 | 67 | builder.write(SCALE); 68 | builder.writeInt(entityId); 69 | builder.writeFloat(scaleX); 70 | builder.writeFloat(scaleY); 71 | builder.writeFloat(scaleZ); 72 | builder.writeInt(duration); 73 | 74 | return builder.build(); 75 | } 76 | 77 | public static Packet color(int entityId, int colorR, int colorG, int colorB, int duration) 78 | { 79 | PacketBuilder builder = PacketBuilder.getInstance(); 80 | 81 | builder.write(COLOR); 82 | builder.writeInt(entityId); 83 | builder.writeByte(colorR); 84 | builder.writeByte(colorG); 85 | builder.writeByte(colorB); 86 | builder.writeInt(duration); 87 | 88 | return builder.build(); 89 | } 90 | 91 | public static Packet colorAndScale(int entityId, int colorR, int colorG, int colorB, float scaleX, float scaleY, float scaleZ, int duration) 92 | { 93 | PacketBuilder builder = PacketBuilder.getInstance(); 94 | 95 | builder.write(COLOR_AND_SCALE); 96 | builder.writeInt(entityId); 97 | builder.writeByte(colorR); 98 | builder.writeByte(colorG); 99 | builder.writeByte(colorB); 100 | builder.writeFloat(scaleX); 101 | builder.writeFloat(scaleY); 102 | builder.writeFloat(scaleZ); 103 | builder.writeInt(duration); 104 | 105 | return builder.build(); 106 | } 107 | 108 | public static Packet fakeEntity(int entityId, int typeId) 109 | { 110 | PacketBuilder builder = PacketBuilder.getInstance(); 111 | 112 | builder.write(FAKE_ENTITY); 113 | builder.writeInt(entityId); 114 | builder.writeByte(typeId); 115 | 116 | return builder.build(); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/CustomEntityPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity; 18 | 19 | import com.github.noonmaru.customentity.cmd.*; 20 | import com.github.noonmaru.tap.command.CommandManager; 21 | import org.bukkit.plugin.java.JavaPlugin; 22 | 23 | public final class CustomEntityPlugin extends JavaPlugin 24 | { 25 | private static CustomEntityPlugin instance; 26 | 27 | public static CustomEntityPlugin getInstance() 28 | { 29 | return instance; 30 | } 31 | 32 | @Override 33 | public void onEnable() 34 | { 35 | getServer().getMessenger().registerOutgoingPluginChannel(this, CustomEntityPacket.CHANNEL); 36 | 37 | instance = this; 38 | 39 | registerCommands(); 40 | 41 | //debug code 42 | /*FakeStandManager manager = new FakeStandManager(); 43 | Map stands = new HashMap<>(); 44 | 45 | getServer().getPluginManager().registerEvents(new Listener() 46 | { 47 | @EventHandler 48 | public void onPlayerJoin(PlayerJoinEvent event) 49 | { 50 | Player player = event.getPlayer(); 51 | Location loc = player.getEyeLocation(); 52 | loc.add(loc.getDirection().multiply(10)); 53 | stands.put(player, manager.create(loc.getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), 0)); 54 | 55 | } 56 | 57 | @EventHandler 58 | public void onPlayerInteract(PlayerInteractEvent event) 59 | { 60 | if (event.getHand() == EquipmentSlot.HAND) 61 | { 62 | if (event.getAction() == Action.RIGHT_CLICK_AIR) 63 | { 64 | 65 | Player player = event.getPlayer(); 66 | Location loc = player.getEyeLocation(); 67 | loc.add(loc.getDirection().multiply(10)); 68 | stands.put(player, manager.create(loc.getWorld(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), 0)); 69 | } 70 | else if (event.getAction() == Action.LEFT_CLICK_AIR) 71 | { 72 | stands.get(event.getPlayer()).setScale(2.0F, 6.0F, 2.0F, 10); 73 | } 74 | } 75 | } 76 | }, this); 77 | 78 | getServer().getScheduler().runTaskTimer(this, () -> { 79 | stands.keySet().removeIf(player -> !player.isOnline()); 80 | 81 | for (Map.Entry entry : stands.entrySet()) 82 | { 83 | Player player = entry.getKey(); 84 | FakeStand stand = entry.getValue(); 85 | Location loc = player.getEyeLocation(); 86 | loc.add(loc.getDirection().multiply(10)); 87 | stand.setPosition(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), 0); 88 | stand.setItem(TapPlayer.wrapPlayer(player).getHeldItemMainHand()); 89 | } 90 | manager.update(); 91 | 92 | }, 0, 1);*/ 93 | } 94 | 95 | private void registerCommands() 96 | { 97 | new CommandManager().addHelp("help").addComponent("register", new CommandCERegister()).addComponent("unregister", new CommandCEUnregister()) 98 | .addComponent("color", new CommandCEColor()).addComponent("scale", new CommandCEScale()).addComponent("colorAndScale", new CommandCEColorAndScale()) 99 | .register(getCommand("customentity")); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/FakeStand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity; 18 | 19 | import com.github.noonmaru.collections.Node; 20 | import com.github.noonmaru.math.Vector; 21 | import com.github.noonmaru.tap.Tap; 22 | import com.github.noonmaru.tap.entity.EntitySelectors; 23 | import com.github.noonmaru.tap.entity.TapArmorStand; 24 | import com.github.noonmaru.tap.item.TapItemStack; 25 | import com.github.noonmaru.tap.math.BoundingBox; 26 | import com.github.noonmaru.tap.math.RayTracer; 27 | import com.github.noonmaru.tap.packet.Packet; 28 | import org.bukkit.World; 29 | import org.bukkit.entity.ArmorStand; 30 | import org.bukkit.entity.Player; 31 | import org.bukkit.inventory.EquipmentSlot; 32 | 33 | import java.util.IdentityHashMap; 34 | import java.util.Iterator; 35 | import java.util.List; 36 | import java.util.Map; 37 | 38 | /** 39 | * @author Nemo 40 | */ 41 | public final class FakeStand 42 | { 43 | private final FakeStandManager manager; 44 | 45 | private final IdentityHashMap trackers = new IdentityHashMap<>(); 46 | 47 | private final TapArmorStand stand; 48 | 49 | private final Vector pos = new Vector(); 50 | 51 | private final Vector prevPos = new Vector(); 52 | 53 | Node node; 54 | 55 | private float yaw, pitch; 56 | 57 | private float scaleX, scaleY, scaleZ; 58 | 59 | private TapItemStack item; 60 | 61 | private boolean enqueued; 62 | 63 | private double trackingRange = 128; 64 | 65 | private int trackingTick; 66 | 67 | private BoundingBox trackerBox; 68 | 69 | private boolean updatePos, updateMeta, updateItem; 70 | 71 | private int updatePosCount; 72 | 73 | public FakeStand(FakeStandManager manager, World world, double x, double y, double z, float yaw, float pitch) 74 | { 75 | this.manager = manager; 76 | stand = Tap.ENTITY.createEntity(ArmorStand.class); 77 | stand.setMarker(true); 78 | stand.setInvisible(true); 79 | stand.setHeadPose(0, 0, 0); 80 | stand.setBukkitWorld(world); 81 | stand.setPositionAndRotation(x, y, z, yaw, pitch); 82 | 83 | this.yaw = yaw; 84 | this.pitch = pitch; 85 | this.scaleX = this.scaleY = this.scaleZ = 1.0F; 86 | 87 | prevPos.set(pos.set(x, y, z)); 88 | } 89 | 90 | void onUpdate() 91 | { 92 | if (updatePos) 93 | { 94 | stand.setPositionAndRotation(pos.x, pos.y, pos.z, yaw, pitch); 95 | 96 | Vector move = pos.copy().subtract(prevPos); 97 | 98 | if (move.length() > 3.9 || ++updatePosCount > 4096) 99 | { 100 | updatePosCount = 0; 101 | sendPacket(Packet.ENTITY.teleport(stand.getBukkitEntity(), pos.x, pos.y, pos.z, yaw, pitch, false)); 102 | } 103 | else 104 | { 105 | sendPacket(Packet.ENTITY.relativeMoveLook(stand.getId(), move.x, move.y, move.z, yaw, pitch, false)); 106 | } 107 | 108 | prevPos.set(pos); 109 | updatePos = false; 110 | } 111 | if (updateMeta) 112 | { 113 | sendPacket(Packet.ENTITY.metadata(stand.getBukkitEntity())); 114 | updateMeta = false; 115 | } 116 | if (updateItem) 117 | { 118 | sendPacket(Packet.ENTITY.equipment(stand.getId(), EquipmentSlot.HEAD, item)); 119 | updateItem = false; 120 | } 121 | 122 | enqueued = false; 123 | } 124 | 125 | void updateTrackers() 126 | { 127 | int trackingTick = ++this.trackingTick; 128 | BoundingBox trackerBox = getTrackerBox(); 129 | World world = stand.getBukkitWorld(); 130 | List newTrackers = trackerBox.getEntities(world, null, EntitySelectors.PLAYER.and(entity -> ((Player) entity).getListeningPluginChannels().contains(CustomEntityPacket.CHANNEL))); 131 | 132 | for (Player newTracker : newTrackers) 133 | { 134 | Tracker tracker = trackers.computeIfAbsent(newTracker, player -> new Tracker()); 135 | 136 | if (tracker.trackingCount == 0) //처음 등록될때 137 | { 138 | ArmorStand bukkitEntity = stand.getBukkitEntity(); 139 | int id = stand.getId(); 140 | Packet.ENTITY.spawnMob(bukkitEntity).sendTo(newTrackers); 141 | Packet.ENTITY.metadata(bukkitEntity).sendTo(newTrackers); 142 | Packet.ENTITY.equipment(id, EquipmentSlot.HEAD, item).sendTo(newTrackers); 143 | CustomEntityPacket.register(id).sendTo(newTrackers); 144 | CustomEntityPacket.scale(id, scaleX, scaleY, scaleZ, 0).sendTo(newTrackers); 145 | } 146 | 147 | tracker.trackingCount = trackingTick; //트래킹 카운트 업데이트 148 | } 149 | 150 | Iterator> iterator = trackers.entrySet().iterator(); 151 | 152 | while (iterator.hasNext()) 153 | { 154 | Map.Entry entry = iterator.next(); 155 | 156 | if (trackingTick != entry.getValue().trackingCount) //범위 밖에 있어서 트래킹 카운트가 올라가지 않았을경우 제거 157 | { 158 | Packet.ENTITY.destroy(stand.getId()).sendTo(entry.getKey()); 159 | iterator.remove(); 160 | } 161 | } 162 | } 163 | 164 | private BoundingBox getTrackerBox() 165 | { 166 | BoundingBox box = this.trackerBox; 167 | 168 | if (box != null) 169 | return box; 170 | 171 | Vector pos = this.pos; 172 | double x = pos.x; 173 | double y = pos.y; 174 | double z = pos.z; 175 | double w = this.trackingRange; 176 | 177 | return this.trackerBox = Tap.MATH.newBoundingBox(x - w, y - w, z - w, x + w, y + w, z + w); 178 | } 179 | 180 | public void setCustomName(String name) 181 | { 182 | stand.setCustomName(name); 183 | 184 | updateMeta(); 185 | } 186 | 187 | public void setCustomNameVisible(boolean visible) 188 | { 189 | stand.setCustomNameVisible(visible); 190 | 191 | updateMeta(); 192 | } 193 | 194 | public void setGlowingTo(boolean glowing, Iterable players) 195 | { 196 | boolean origin = isGlowing(); 197 | 198 | if (origin == glowing) 199 | { 200 | Packet.ENTITY.metadata(stand.getBukkitEntity()).sendTo(players); 201 | } 202 | else 203 | { 204 | stand.setGlowing(glowing); 205 | Packet.ENTITY.metadata(stand.getBukkitEntity()).sendTo(players); 206 | stand.setGlowing(origin); 207 | } 208 | } 209 | 210 | public boolean isGlowing() 211 | { 212 | return stand.isGlowing(); 213 | } 214 | 215 | public void setGlowing(boolean glowing) 216 | { 217 | stand.setGlowing(glowing); 218 | 219 | updateMeta(); 220 | } 221 | 222 | public TapItemStack getItem() 223 | { 224 | return item == null ? null : item.copy(); 225 | } 226 | 227 | public void setItem(TapItemStack item) 228 | { 229 | this.item = item == null ? null : item.copy(); 230 | 231 | updateItem(); 232 | } 233 | 234 | public void setPosition(Vector pos, float yaw, float pitch) 235 | { 236 | setPosition(pos.x, pos.y, pos.z, yaw, pitch); 237 | } 238 | 239 | public void setPosition(double x, double y, double z, float yaw, float pitch) 240 | { 241 | pos.set(x, y, z); 242 | this.yaw = yaw; 243 | this.pitch = pitch; 244 | this.trackerBox = null; 245 | 246 | updatePos = true; 247 | enqueue(); 248 | } 249 | 250 | public Vector getPosition() 251 | { 252 | return pos.copy(); 253 | } 254 | 255 | public float getYaw() 256 | { 257 | return stand.getYaw(); 258 | } 259 | 260 | public float getPitch() 261 | { 262 | return stand.getPitch(); 263 | } 264 | 265 | public void move(Vector vector, float yaw, float pitch) 266 | { 267 | move(vector.x, vector.y, vector.z, yaw, pitch); 268 | } 269 | 270 | private void move(double x, double y, double z, float yaw, float pitch) 271 | { 272 | setPosition(prevPos.x + x, prevPos.y + y, prevPos.z + z, yaw, pitch); 273 | } 274 | 275 | public RayTracer createRayTracer() 276 | { 277 | return Tap.MATH.newRayTraceCalculator(prevPos, pos); 278 | } 279 | 280 | private void enqueue() 281 | { 282 | if (enqueued) 283 | return; 284 | 285 | enqueued = true; 286 | manager.enqueue(this); 287 | } 288 | 289 | public void setPose(float x, float y, float z) 290 | { 291 | stand.setHeadPose(x, y, z); 292 | 293 | updateMeta(); 294 | } 295 | 296 | private void updateMeta() 297 | { 298 | updateMeta = true; 299 | enqueue(); 300 | } 301 | 302 | public float getScaleX() 303 | { 304 | return scaleX; 305 | } 306 | 307 | public float getScaleY() 308 | { 309 | return scaleY; 310 | } 311 | 312 | public float getScaleZ() 313 | { 314 | return scaleZ; 315 | } 316 | 317 | public void setScale(float scaleX, float scaleY, float scaleZ, int period) 318 | { 319 | this.scaleX = scaleX; 320 | this.scaleY = scaleY; 321 | this.scaleZ = scaleZ; 322 | 323 | sendPacket(CustomEntityPacket.scale(stand.getId(), scaleX, scaleY, scaleZ, period)); 324 | } 325 | 326 | public void setScale(float scale, int period) 327 | { 328 | setScale(scale, scale, scale, period); 329 | } 330 | 331 | public void setTrackerRange(double trackingRange) 332 | { 333 | this.trackingRange = trackingRange; 334 | } 335 | 336 | public boolean isValid() 337 | { 338 | return node != null; 339 | } 340 | 341 | public void remove() 342 | { 343 | if (!isValid()) 344 | return; 345 | 346 | sendPacket(Packet.ENTITY.destroy(stand.getId())); 347 | sendPacket(CustomEntityPacket.unregister(stand.getId())); 348 | trackers.clear(); 349 | node.clear(); 350 | node = null; 351 | } 352 | 353 | private void updateItem() 354 | { 355 | updateItem = true; 356 | enqueue(); 357 | } 358 | 359 | private void sendPacket(Packet packet) 360 | { 361 | packet.sendTo(trackers.keySet()); 362 | } 363 | 364 | private static class Tracker 365 | { 366 | int trackingCount; 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/FakeStandManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity; 18 | 19 | import com.github.noonmaru.collections.mut.LinkedNodeList; 20 | import org.bukkit.World; 21 | 22 | import java.util.ArrayDeque; 23 | 24 | /** 25 | * @author Nemo 26 | */ 27 | public class FakeStandManager 28 | { 29 | 30 | private final LinkedNodeList stands = new LinkedNodeList<>(); 31 | 32 | private final ArrayDeque queue = new ArrayDeque<>(); 33 | 34 | private final ArrayDeque trackerQueue = new ArrayDeque<>(); 35 | 36 | private double trackerCount; 37 | 38 | private double trackerUpdatePerTick; 39 | 40 | public FakeStand create(World world, double x, double y, double z, float yaw, float pitch) 41 | { 42 | FakeStand newStand = new FakeStand(this, world, x, y, z, yaw, pitch); 43 | newStand.node = stands.addFirstNode(newStand); 44 | newStand.updateTrackers(); 45 | 46 | return newStand; 47 | } 48 | 49 | void enqueue(FakeStand stand) 50 | { 51 | this.queue.offer(stand); 52 | } 53 | 54 | /** 55 | * 이 메서드를 Tick마다 호출해주세요! 56 | */ 57 | public void update() 58 | { 59 | updateStands(); 60 | updateTrackers(); 61 | } 62 | 63 | private void updateStands() 64 | { 65 | FakeStand stand; 66 | 67 | while ((stand = queue.poll()) != null) 68 | { 69 | if (stand.isValid()) 70 | stand.onUpdate(); 71 | } 72 | } 73 | 74 | private void recalculateUpdatePerTick() 75 | { 76 | trackerCount = 0.0D; 77 | trackerUpdatePerTick = stands.size() / 40.0D; /*Math.max(1.0D, 1.0 - Math.pow(0.5, (stands.size() - 20) / 20.0D));*/ 78 | } 79 | 80 | private void updateTrackers() 81 | { 82 | if (trackerQueue.isEmpty()) 83 | { 84 | recalculateUpdatePerTick(); 85 | trackerQueue.addAll(stands); 86 | } 87 | 88 | int count = (int) (trackerCount += trackerUpdatePerTick); 89 | trackerCount -= count; 90 | FakeStand stand; 91 | 92 | while (count > 0 && (stand = trackerQueue.poll()) != null) 93 | { 94 | if (stand.isValid()) 95 | { 96 | count--; 97 | stand.updateTrackers(); 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCE.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.math.Vector; 20 | import com.github.noonmaru.tap.Tap; 21 | import com.github.noonmaru.tap.command.ArgumentList; 22 | import com.github.noonmaru.tap.command.CommandComponent; 23 | import com.github.noonmaru.tap.entity.EntitySelectors; 24 | import com.github.noonmaru.tap.math.RayTraceResult; 25 | import org.bukkit.Location; 26 | import org.bukkit.command.Command; 27 | import org.bukkit.command.CommandSender; 28 | import org.bukkit.entity.Entity; 29 | import org.bukkit.entity.LivingEntity; 30 | import org.bukkit.entity.Player; 31 | 32 | import java.util.List; 33 | 34 | 35 | public abstract class CommandCE extends CommandComponent 36 | { 37 | public CommandCE(String usage, String description, String permission) 38 | { 39 | this(usage, description, permission, 0); 40 | } 41 | 42 | public CommandCE(String usage, String description, String permission, int argumentsLength) 43 | { 44 | super(usage == null ? "|target" : "|target " + usage, description, permission, Math.max(0, argumentsLength) + 1); 45 | } 46 | 47 | @Override 48 | public final boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, ArgumentList args) 49 | { 50 | String token = args.next(); 51 | 52 | try 53 | { 54 | return onCommand(sender, command, label, componentLabel, Integer.parseInt(token), args); 55 | } 56 | catch (NumberFormatException e) 57 | {} 58 | 59 | if ("target".equalsIgnoreCase(token)) 60 | { 61 | if (sender instanceof Player) 62 | { 63 | Player player = (Player) sender; 64 | Location loc = player.getEyeLocation(); 65 | org.bukkit.util.Vector vec = loc.getDirection().multiply(256D); 66 | Vector from = new Vector(loc.getX(), loc.getY(), loc.getZ()); 67 | Vector to = from.copy().add(vec.getX(), vec.getY(), vec.getZ()); 68 | RayTraceResult result = Tap.MATH.rayTrace(loc.getWorld(), player, from, to, 0, 1.0D, EntitySelectors.CREATURE); 69 | 70 | if (result != null) 71 | { 72 | LivingEntity target = result.getEntity(); 73 | 74 | if (target != null) 75 | return onCommand(sender, command, label, componentLabel, target.getEntityId(), args); 76 | } 77 | 78 | sender.sendMessage("적용할 엔티티를 바라보고 사용하세요."); 79 | return true; 80 | } 81 | } 82 | 83 | List entities = matchEntities(sender, token, Entity.class); 84 | int cursor = args.getCursor(); 85 | 86 | for (Entity entity : entities) 87 | { 88 | if (entity instanceof Player) 89 | continue; 90 | 91 | if (!onCommand(sender, command, label, componentLabel, entity.getEntityId(), args.setCursor(cursor))) 92 | return false; 93 | } 94 | 95 | return true; 96 | } 97 | 98 | public abstract boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args); 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCEColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.customentity.CustomEntityPacket; 20 | import com.github.noonmaru.tap.command.ArgumentList; 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | 24 | public class CommandCEColor extends CommandCE 25 | { 26 | 27 | public CommandCEColor() 28 | { 29 | super(" [Duration]", "색상을 적용합니다.", "customentity.color", 1); 30 | } 31 | 32 | @Override 33 | public boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args) 34 | { 35 | try 36 | { 37 | int color = Integer.decode("0x" + args.next()); 38 | int r = (color >> 16) & 0xFF; 39 | int g = (color >> 8) & 0xFF; 40 | int b = color & 0xFF; 41 | int duration = args.hasNext() ? Math.max(0, Integer.parseInt(args.next())) : 0; 42 | 43 | CustomEntityPacket.color(entityId, r, g, b, duration).sendAll(); 44 | broadcast(sender, label, componentLabel, String.format("%d -> %02X%02X%02X %d", entityId, r, g, b, duration)); 45 | } 46 | catch (NumberFormatException e) 47 | { 48 | return false; 49 | } 50 | 51 | return true; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCEColorAndScale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.customentity.CustomEntityPacket; 20 | import com.github.noonmaru.tap.command.ArgumentList; 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | 24 | public class CommandCEColorAndScale extends CommandCE 25 | { 26 | 27 | public CommandCEColorAndScale() 28 | { 29 | super(" [Duration]", "색상과 크기를 적용합니다.", "customentity.colorandscale"); 30 | } 31 | 32 | @Override 33 | public boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args) 34 | { 35 | try 36 | { 37 | int color = Integer.decode("0x" + args.next()); 38 | int r = (color >> 16) & 0xFF; 39 | int g = (color >> 8) & 0xFF; 40 | int b = color & 0xFF; 41 | float scaleX = args.nextFloat(); 42 | float scaleY = args.nextFloat(); 43 | float scaleZ = args.nextFloat(); 44 | int duration = args.hasNext() ? Math.max(0, Integer.parseInt(args.next())) : 0; 45 | 46 | CustomEntityPacket.colorAndScale(entityId, r, g, b, scaleX, scaleY, scaleZ, duration).sendAll(); 47 | broadcast(sender, label, componentLabel, String.format("%d -> %02X%02X%02X %.1f %.1f %.1f %d", entityId, r, g, b, scaleX, scaleY, scaleZ, duration)); 48 | } 49 | catch (NumberFormatException e) 50 | { 51 | return false; 52 | } 53 | 54 | return true; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCERegister.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.customentity.CustomEntityPacket; 20 | import com.github.noonmaru.tap.command.ArgumentList; 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | 24 | public class CommandCERegister extends CommandCE 25 | { 26 | 27 | public CommandCERegister() 28 | { 29 | super(null, "CustomEntity로 등록합니다.", "customentity.register"); 30 | } 31 | 32 | @Override 33 | public boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args) 34 | { 35 | CustomEntityPacket.register(entityId).sendAll(); 36 | broadcast(sender, label, componentLabel, String.valueOf(entityId)); 37 | 38 | return true; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCEScale.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.customentity.CustomEntityPacket; 20 | import com.github.noonmaru.tap.command.ArgumentList; 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | 24 | public class CommandCEScale extends CommandCE 25 | { 26 | 27 | public CommandCEScale() 28 | { 29 | super(" [Duration]", "크기를 적용합니다.", "customentity.scale", 3); 30 | } 31 | 32 | @Override 33 | public boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args) 34 | { 35 | try 36 | { 37 | float scaleX = Float.parseFloat(args.next()); 38 | float scaleY = Float.parseFloat(args.next()); 39 | float scaleZ = Float.parseFloat(args.next()); 40 | int duration = args.hasNext() ? Math.max(0, Integer.parseInt(args.next())) : 0; 41 | 42 | CustomEntityPacket.scale(entityId, scaleX, scaleY, scaleZ, duration).sendAll(); 43 | broadcast(sender, label, componentLabel, String.format("%d -> %.1f %.1f %.1f %d", entityId, scaleX, scaleY, scaleZ, duration)); 44 | } 45 | catch (NumberFormatException e) 46 | { 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/cmd/CommandCEUnregister.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.cmd; 18 | 19 | import com.github.noonmaru.customentity.CustomEntityPacket; 20 | import com.github.noonmaru.tap.command.ArgumentList; 21 | import org.bukkit.command.Command; 22 | import org.bukkit.command.CommandSender; 23 | 24 | public class CommandCEUnregister extends CommandCE 25 | { 26 | 27 | public CommandCEUnregister() 28 | { 29 | super(null, "CustomEntity를 해제합니다.", "customentity.unregister"); 30 | } 31 | 32 | @Override 33 | public boolean onCommand(CommandSender sender, Command command, String label, String componentLabel, int entityId, ArgumentList args) 34 | { 35 | CustomEntityPacket.unregister(entityId).sendAll(); 36 | 37 | return true; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/github/noonmaru/customentity/util/PacketBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Noonmaru 3 | * 4 | * Licensed under the General Public License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://opensource.org/licenses/gpl-2.0.php 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.github.noonmaru.customentity.util; 18 | 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.DataOutput; 21 | import java.io.DataOutputStream; 22 | import java.io.IOException; 23 | 24 | import com.github.noonmaru.customentity.CustomEntityPacket; 25 | import com.github.noonmaru.tap.packet.Packet; 26 | import com.google.common.base.Charsets; 27 | 28 | 29 | public final class PacketBuilder implements DataOutput 30 | { 31 | private static final PacketBuilder INSTANCE = new PacketBuilder(); 32 | 33 | public static PacketBuilder getInstance() 34 | { 35 | INSTANCE.reset(); 36 | 37 | return INSTANCE; 38 | } 39 | 40 | private final ByteArrayOutputStream bOut; 41 | 42 | private final DataOutputStream dOut; 43 | 44 | private PacketBuilder() 45 | { 46 | ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 47 | 48 | this.bOut = bOut; 49 | this.dOut = new DataOutputStream(bOut); 50 | } 51 | 52 | @Override 53 | public void write(int b) 54 | { 55 | this.bOut.write(b); 56 | } 57 | 58 | @Override 59 | public void write(byte[] b) 60 | { 61 | try 62 | { 63 | this.bOut.write(b); 64 | } 65 | catch (IOException e) 66 | { 67 | throw new AssertionError(e); 68 | } 69 | } 70 | 71 | @Override 72 | public void write(byte[] b, int off, int len) 73 | { 74 | this.bOut.write(b, off, len); 75 | } 76 | 77 | @Override 78 | public void writeBoolean(boolean v) 79 | { 80 | try 81 | { 82 | this.dOut.writeBoolean(v); 83 | } 84 | catch (IOException e) 85 | { 86 | throw new AssertionError(e); 87 | } 88 | } 89 | 90 | @Override 91 | public void writeByte(int v) 92 | { 93 | try 94 | { 95 | this.dOut.writeByte(v); 96 | } 97 | catch (IOException e) 98 | { 99 | throw new AssertionError(e); 100 | } 101 | } 102 | 103 | @Override 104 | public void writeShort(int v) 105 | { 106 | try 107 | { 108 | this.dOut.writeShort(v); 109 | } 110 | catch (IOException e) 111 | { 112 | throw new AssertionError(e); 113 | } 114 | } 115 | 116 | @Override 117 | public void writeChar(int v) 118 | { 119 | try 120 | { 121 | this.dOut.writeChar(v); 122 | } 123 | catch (IOException e) 124 | { 125 | throw new AssertionError(e); 126 | } 127 | } 128 | 129 | @Override 130 | public void writeInt(int v) 131 | { 132 | try 133 | { 134 | this.dOut.writeInt(v); 135 | } 136 | catch (IOException e) 137 | { 138 | throw new AssertionError(e); 139 | } 140 | } 141 | 142 | @Override 143 | public void writeLong(long v) 144 | { 145 | try 146 | { 147 | this.dOut.writeLong(v); 148 | } 149 | catch (IOException e) 150 | { 151 | throw new AssertionError(e); 152 | } 153 | } 154 | 155 | @Override 156 | public void writeFloat(float v) 157 | { 158 | try 159 | { 160 | this.dOut.writeFloat(v); 161 | } 162 | catch (IOException e) 163 | { 164 | throw new AssertionError(e); 165 | } 166 | } 167 | 168 | @Override 169 | public void writeDouble(double v) 170 | { 171 | try 172 | { 173 | this.dOut.writeDouble(v); 174 | } 175 | catch (IOException e) 176 | { 177 | throw new AssertionError(e); 178 | } 179 | } 180 | 181 | @Override 182 | public void writeBytes(String s) 183 | { 184 | try 185 | { 186 | this.dOut.writeBytes(s); 187 | } 188 | catch (IOException e) 189 | { 190 | throw new AssertionError(e); 191 | } 192 | } 193 | 194 | @Override 195 | public void writeChars(String s) 196 | { 197 | try 198 | { 199 | this.dOut.writeChars(s); 200 | } 201 | catch (IOException e) 202 | { 203 | throw new AssertionError(e); 204 | } 205 | } 206 | 207 | @Override 208 | public void writeUTF(String s) 209 | { 210 | try 211 | { 212 | this.dOut.writeUTF(s); 213 | } 214 | catch (IOException e) 215 | { 216 | throw new AssertionError(e); 217 | } 218 | } 219 | 220 | public void writeString(String s) 221 | { 222 | if (s == null) 223 | { 224 | try 225 | { 226 | this.dOut.writeShort(0); 227 | } 228 | catch (IOException e) 229 | { 230 | throw new AssertionError(e); 231 | } 232 | return; 233 | } 234 | 235 | byte[] bytes = s.getBytes(Charsets.UTF_8); 236 | 237 | try 238 | { 239 | this.dOut.writeShort(bytes.length); 240 | this.dOut.write(bytes); 241 | } 242 | catch (IOException e) 243 | { 244 | throw new AssertionError(e); 245 | } 246 | } 247 | 248 | public void reset() 249 | { 250 | this.bOut.reset(); 251 | } 252 | 253 | public byte[] toByteArray() 254 | { 255 | return this.bOut.toByteArray(); 256 | } 257 | 258 | public Packet build() 259 | { 260 | return Packet.CUSTOM.payload(CustomEntityPacket.CHANNEL, toByteArray()); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: CustomEntity 2 | version: @version@ 3 | main: com.github.noonmaru.customentity.CustomEntityPlugin 4 | depend: [Tap] 5 | authors: [Nemo] 6 | commands: 7 | customentity: 8 | aliases: [ce] 9 | usage: / help --------------------------------------------------------------------------------