Advertisement
Guest User

Untitled

a guest
Sep 27th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 86.82 KB | None | 0 0
  1. package org.kcpdev.framework.particles;
  2.  
  3. import java.lang.reflect.Constructor;
  4. import java.lang.reflect.Field;
  5. import java.lang.reflect.Method;
  6. import java.util.Arrays;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.Map.Entry;
  11.  
  12. import org.bukkit.Bukkit;
  13. import org.bukkit.Color;
  14. import org.bukkit.Location;
  15. import org.bukkit.Material;
  16. import org.bukkit.entity.Player;
  17. import org.bukkit.util.Vector;
  18. import org.kcpdev.framework.particles.ReflectionUtils.PackageType;
  19.  
  20. /**
  21. * <b>ParticleEffect Library</b>
  22. * <p>
  23. * This library was created by @DarkBlade12 and allows you to display all Minecraft particle effects on a Bukkit server
  24. * <p>
  25. * You are welcome to use it, modify it and redistribute it under the following conditions:
  26. * <ul>
  27. * <li>Don't claim this class as your own
  28. * <li>Don't remove this disclaimer
  29. * </ul>
  30. * <p>
  31. * Special thanks:
  32. * <ul>
  33. * <li>@microgeek (original idea, names and packet parameters)
  34. * <li>@ShadyPotato (1.8 names, ids and packet parameters)
  35. * <li>@RingOfStorms (particle behavior)
  36. * <li>@Cybermaxke (particle behavior)
  37. * </ul>
  38. * <p>
  39. * <i>It would be nice if you provide credit to me if you use this class in a published project</i>
  40. *
  41. * @author DarkBlade12
  42. * @version 1.7
  43. */
  44. public enum ParticleEffect {
  45. /**
  46. * A particle effect which is displayed by exploding tnt and creepers:
  47. * <ul>
  48. * <li>It looks like a white cloud
  49. * <li>The speed value influences the velocity at which the particle flies off
  50. * </ul>
  51. */
  52. EXPLOSION_NORMAL("explode", 0, -1, ParticleProperty.DIRECTIONAL),
  53. /**
  54. * A particle effect which is displayed by exploding ghast fireballs and wither skulls:
  55. * <ul>
  56. * <li>It looks like a gray ball which is fading away
  57. * <li>The speed value slightly influences the size of this particle effect
  58. * </ul>
  59. */
  60. EXPLOSION_LARGE("largeexplode", 1, -1),
  61. /**
  62. * A particle effect which is displayed by exploding tnt and creepers:
  63. * <ul>
  64. * <li>It looks like a crowd of gray balls which are fading away
  65. * <li>The speed value has no influence on this particle effect
  66. * </ul>
  67. */
  68. EXPLOSION_HUGE("hugeexplosion", 2, -1),
  69. /**
  70. * A particle effect which is displayed by launching fireworks:
  71. * <ul>
  72. * <li>It looks like a white star which is sparkling
  73. * <li>The speed value influences the velocity at which the particle flies off
  74. * </ul>
  75. */
  76. FIREWORKS_SPARK("fireworksSpark", 3, -1, ParticleProperty.DIRECTIONAL),
  77. /**
  78. * A particle effect which is displayed by swimming entities and arrows in water:
  79. * <ul>
  80. * <li>It looks like a bubble
  81. * <li>The speed value influences the velocity at which the particle flies off
  82. * </ul>
  83. */
  84. WATER_BUBBLE("bubble", 4, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_WATER),
  85. /**
  86. * A particle effect which is displayed by swimming entities and shaking wolves:
  87. * <ul>
  88. * <li>It looks like a blue drop
  89. * <li>The speed value has no influence on this particle effect
  90. * </ul>
  91. */
  92. WATER_SPLASH("splash", 5, -1, ParticleProperty.DIRECTIONAL),
  93. /**
  94. * A particle effect which is displayed on water when fishing:
  95. * <ul>
  96. * <li>It looks like a blue droplet
  97. * <li>The speed value influences the velocity at which the particle flies off
  98. * </ul>
  99. */
  100. WATER_WAKE("wake", 6, 7, ParticleProperty.DIRECTIONAL),
  101. /**
  102. * A particle effect which is displayed by water:
  103. * <ul>
  104. * <li>It looks like a tiny blue square
  105. * <li>The speed value has no influence on this particle effect
  106. * </ul>
  107. */
  108. SUSPENDED("suspended", 7, -1, ParticleProperty.REQUIRES_WATER),
  109. /**
  110. * A particle effect which is displayed by air when close to bedrock and the in the void:
  111. * <ul>
  112. * <li>It looks like a tiny gray square
  113. * <li>The speed value has no influence on this particle effect
  114. * </ul>
  115. */
  116. SUSPENDED_DEPTH("depthSuspend", 8, -1, ParticleProperty.DIRECTIONAL),
  117. /**
  118. * A particle effect which is displayed when landing a critical hit and by arrows:
  119. * <ul>
  120. * <li>It looks like a light brown cross
  121. * <li>The speed value influences the velocity at which the particle flies off
  122. * </ul>
  123. */
  124. CRIT("crit", 9, -1, ParticleProperty.DIRECTIONAL),
  125. /**
  126. * A particle effect which is displayed when landing a hit with an enchanted weapon:
  127. * <ul>
  128. * <li>It looks like a cyan star
  129. * <li>The speed value influences the velocity at which the particle flies off
  130. * </ul>
  131. */
  132. CRIT_MAGIC("magicCrit", 10, -1, ParticleProperty.DIRECTIONAL),
  133. /**
  134. * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners:
  135. * <ul>
  136. * <li>It looks like a little gray cloud
  137. * <li>The speed value influences the velocity at which the particle flies off
  138. * </ul>
  139. */
  140. SMOKE_NORMAL("smoke", 11, -1, ParticleProperty.DIRECTIONAL),
  141. /**
  142. * A particle effect which is displayed by fire, minecarts with furnace and blazes:
  143. * <ul>
  144. * <li>It looks like a large gray cloud
  145. * <li>The speed value influences the velocity at which the particle flies off
  146. * </ul>
  147. */
  148. SMOKE_LARGE("largesmoke", 12, -1, ParticleProperty.DIRECTIONAL),
  149. /**
  150. * A particle effect which is displayed when splash potions or bottles o' enchanting hit something:
  151. * <ul>
  152. * <li>It looks like a white swirl
  153. * <li>The speed value causes the particle to only move upwards when set to 0
  154. * <li>Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0
  155. * </ul>
  156. */
  157. SPELL("spell", 13, -1),
  158. /**
  159. * A particle effect which is displayed when instant splash potions hit something:
  160. * <ul>
  161. * <li>It looks like a white cross
  162. * <li>The speed value causes the particle to only move upwards when set to 0
  163. * <li>Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0
  164. * </ul>
  165. */
  166. SPELL_INSTANT("instantSpell", 14, -1),
  167. /**
  168. * A particle effect which is displayed by entities with active potion effects:
  169. * <ul>
  170. * <li>It looks like a colored swirl
  171. * <li>The speed value causes the particle to be colored black when set to 0
  172. * <li>The particle color gets lighter when increasing the speed and darker when decreasing the speed
  173. * </ul>
  174. */
  175. SPELL_MOB("mobSpell", 15, -1, ParticleProperty.COLORABLE),
  176. /**
  177. * A particle effect which is displayed by entities with active potion effects applied through a beacon:
  178. * <ul>
  179. * <li>It looks like a transparent colored swirl
  180. * <li>The speed value causes the particle to be always colored black when set to 0
  181. * <li>The particle color gets lighter when increasing the speed and darker when decreasing the speed
  182. * </ul>
  183. */
  184. SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1, ParticleProperty.COLORABLE),
  185. /**
  186. * A particle effect which is displayed by witches:
  187. * <ul>
  188. * <li>It looks like a purple cross
  189. * <li>The speed value causes the particle to only move upwards when set to 0
  190. * <li>Only the motion on the y-axis can be controlled, the motion on the x- and z-axis are multiplied by 0.1 when setting the values to 0
  191. * </ul>
  192. */
  193. SPELL_WITCH("witchMagic", 17, -1),
  194. /**
  195. * A particle effect which is displayed by blocks beneath a water source:
  196. * <ul>
  197. * <li>It looks like a blue drip
  198. * <li>The speed value has no influence on this particle effect
  199. * </ul>
  200. */
  201. DRIP_WATER("dripWater", 18, -1),
  202. /**
  203. * A particle effect which is displayed by blocks beneath a lava source:
  204. * <ul>
  205. * <li>It looks like an orange drip
  206. * <li>The speed value has no influence on this particle effect
  207. * </ul>
  208. */
  209. DRIP_LAVA("dripLava", 19, -1),
  210. /**
  211. * A particle effect which is displayed when attacking a villager in a village:
  212. * <ul>
  213. * <li>It looks like a cracked gray heart
  214. * <li>The speed value has no influence on this particle effect
  215. * </ul>
  216. */
  217. VILLAGER_ANGRY("angryVillager", 20, -1),
  218. /**
  219. * A particle effect which is displayed when using bone meal and trading with a villager in a village:
  220. * <ul>
  221. * <li>It looks like a green star
  222. * <li>The speed value has no influence on this particle effect
  223. * </ul>
  224. */
  225. VILLAGER_HAPPY("happyVillager", 21, -1, ParticleProperty.DIRECTIONAL),
  226. /**
  227. * A particle effect which is displayed by mycelium:
  228. * <ul>
  229. * <li>It looks like a tiny gray square
  230. * <li>The speed value has no influence on this particle effect
  231. * </ul>
  232. */
  233. TOWN_AURA("townaura", 22, -1, ParticleProperty.DIRECTIONAL),
  234. /**
  235. * A particle effect which is displayed by note blocks:
  236. * <ul>
  237. * <li>It looks like a colored note
  238. * <li>The speed value causes the particle to be colored green when set to 0
  239. * </ul>
  240. */
  241. NOTE("note", 23, -1, ParticleProperty.COLORABLE),
  242. /**
  243. * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs:
  244. * <ul>
  245. * <li>It looks like a purple cloud
  246. * <li>The speed value influences the spread of this particle effect
  247. * </ul>
  248. */
  249. PORTAL("portal", 24, -1, ParticleProperty.DIRECTIONAL),
  250. /**
  251. * A particle effect which is displayed by enchantment tables which are nearby bookshelves:
  252. * <ul>
  253. * <li>It looks like a cryptic white letter
  254. * <li>The speed value influences the spread of this particle effect
  255. * </ul>
  256. */
  257. ENCHANTMENT_TABLE("enchantmenttable", 25, -1, ParticleProperty.DIRECTIONAL),
  258. /**
  259. * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners:
  260. * <ul>
  261. * <li>It looks like a tiny flame
  262. * <li>The speed value influences the velocity at which the particle flies off
  263. * </ul>
  264. */
  265. FLAME("flame", 26, -1, ParticleProperty.DIRECTIONAL),
  266. /**
  267. * A particle effect which is displayed by lava:
  268. * <ul>
  269. * <li>It looks like a spark
  270. * <li>The speed value has no influence on this particle effect
  271. * </ul>
  272. */
  273. LAVA("lava", 27, -1),
  274. /**
  275. * A particle effect which is currently unused:
  276. * <ul>
  277. * <li>It looks like a transparent gray square
  278. * <li>The speed value has no influence on this particle effect
  279. * </ul>
  280. */
  281. FOOTSTEP("footstep", 28, -1),
  282. /**
  283. * A particle effect which is displayed when a mob dies:
  284. * <ul>
  285. * <li>It looks like a large white cloud
  286. * <li>The speed value influences the velocity at which the particle flies off
  287. * </ul>
  288. */
  289. CLOUD("cloud", 29, -1, ParticleProperty.DIRECTIONAL),
  290. /**
  291. * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters:
  292. * <ul>
  293. * <li>It looks like a tiny colored cloud
  294. * <li>The speed value causes the particle to be colored red when set to 0
  295. * </ul>
  296. */
  297. REDSTONE("reddust", 30, -1, ParticleProperty.COLORABLE),
  298. /**
  299. * A particle effect which is displayed when snowballs hit a block:
  300. * <ul>
  301. * <li>It looks like a little piece with the snowball texture
  302. * <li>The speed value has no influence on this particle effect
  303. * </ul>
  304. */
  305. SNOWBALL("snowballpoof", 31, -1),
  306. /**
  307. * A particle effect which is currently unused:
  308. * <ul>
  309. * <li>It looks like a tiny white cloud
  310. * <li>The speed value influences the velocity at which the particle flies off
  311. * </ul>
  312. */
  313. SNOW_SHOVEL("snowshovel", 32, -1, ParticleProperty.DIRECTIONAL),
  314. /**
  315. * A particle effect which is displayed by slimes:
  316. * <ul>
  317. * <li>It looks like a tiny part of the slimeball icon
  318. * <li>The speed value has no influence on this particle effect
  319. * </ul>
  320. */
  321. SLIME("slime", 33, -1),
  322. /**
  323. * A particle effect which is displayed when breeding and taming animals:
  324. * <ul>
  325. * <li>It looks like a red heart
  326. * <li>The speed value has no influence on this particle effect
  327. * </ul>
  328. */
  329. HEART("heart", 34, -1),
  330. /**
  331. * A particle effect which is displayed by barriers:
  332. * <ul>
  333. * <li>It looks like a red box with a slash through it
  334. * <li>The speed value has no influence on this particle effect
  335. * </ul>
  336. */
  337. BARRIER("barrier", 35, 8),
  338. /**
  339. * A particle effect which is displayed when breaking a tool or eggs hit a block:
  340. * <ul>
  341. * <li>It looks like a little piece with an item texture
  342. * </ul>
  343. */
  344. ITEM_CRACK("iconcrack", 36, -1, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA),
  345. /**
  346. * A particle effect which is displayed when breaking blocks or sprinting:
  347. * <ul>
  348. * <li>It looks like a little piece with a block texture
  349. * <li>The speed value has no influence on this particle effect
  350. * </ul>
  351. */
  352. BLOCK_CRACK("blockcrack", 37, -1, ParticleProperty.REQUIRES_DATA),
  353. /**
  354. * A particle effect which is displayed when falling:
  355. * <ul>
  356. * <li>It looks like a little piece with a block texture
  357. * </ul>
  358. */
  359. BLOCK_DUST("blockdust", 38, 7, ParticleProperty.DIRECTIONAL, ParticleProperty.REQUIRES_DATA),
  360. /**
  361. * A particle effect which is displayed when rain hits the ground:
  362. * <ul>
  363. * <li>It looks like a blue droplet
  364. * <li>The speed value has no influence on this particle effect
  365. * </ul>
  366. */
  367. WATER_DROP("droplet", 39, 8),
  368. /**
  369. * A particle effect which is currently unused:
  370. * <ul>
  371. * <li>It has no visual effect
  372. * </ul>
  373. */
  374. ITEM_TAKE("take", 40, 8),
  375. /**
  376. * A particle effect which is displayed by elder guardians:
  377. * <ul>
  378. * <li>It looks like the shape of the elder guardian
  379. * <li>The speed value has no influence on this particle effect
  380. * <li>The offset values have no influence on this particle effect
  381. * </ul>
  382. */
  383. MOB_APPEARANCE("mobappearance", 41, 8);
  384.  
  385. private static final Map<String, ParticleEffect> NAME_MAP = new HashMap<String, ParticleEffect>();
  386. private static final Map<Integer, ParticleEffect> ID_MAP = new HashMap<Integer, ParticleEffect>();
  387. private final String name;
  388. private final int id;
  389. private final int requiredVersion;
  390. private final List<ParticleProperty> properties;
  391.  
  392. // Initialize map for quick name and id lookup
  393. static {
  394. for (ParticleEffect effect : values()) {
  395. NAME_MAP.put(effect.name, effect);
  396. ID_MAP.put(effect.id, effect);
  397. }
  398. }
  399.  
  400. /**
  401. * Construct a new particle effect
  402. *
  403. * @param name Name of this particle effect
  404. * @param id Id of this particle effect
  405. * @param requiredVersion Version which is required (1.x)
  406. * @param properties Properties of this particle effect
  407. */
  408. private ParticleEffect(String name, int id, int requiredVersion, ParticleProperty... properties) {
  409. this.name = name;
  410. this.id = id;
  411. this.requiredVersion = requiredVersion;
  412. this.properties = Arrays.asList(properties);
  413. }
  414.  
  415. /**
  416. * Returns the name of this particle effect
  417. *
  418. * @return The name
  419. */
  420. public String getName() {
  421. return name;
  422. }
  423.  
  424. /**
  425. * Returns the id of this particle effect
  426. *
  427. * @return The id
  428. */
  429. public int getId() {
  430. return id;
  431. }
  432.  
  433. /**
  434. * Returns the required version for this particle effect (1.x)
  435. *
  436. * @return The required version
  437. */
  438. public int getRequiredVersion() {
  439. return requiredVersion;
  440. }
  441.  
  442. /**
  443. * Determine if this particle effect has a specific property
  444. *
  445. * @return Whether it has the property or not
  446. */
  447. public boolean hasProperty(ParticleProperty property) {
  448. return properties.contains(property);
  449. }
  450.  
  451. /**
  452. * Determine if this particle effect is supported by your current server version
  453. *
  454. * @return Whether the particle effect is supported or not
  455. */
  456. public boolean isSupported() {
  457. if (requiredVersion == -1) {
  458. return true;
  459. }
  460. return ParticlePacket.getVersion() >= requiredVersion;
  461. }
  462.  
  463. /**
  464. * Returns the particle effect with the given name
  465. *
  466. * @param name Name of the particle effect
  467. * @return The particle effect
  468. */
  469. public static ParticleEffect fromName(String name) {
  470. for (Entry<String, ParticleEffect> entry : NAME_MAP.entrySet()) {
  471. if (!entry.getKey().equalsIgnoreCase(name)) {
  472. continue;
  473. }
  474. return entry.getValue();
  475. }
  476. return null;
  477. }
  478.  
  479. /**
  480. * Returns the particle effect with the given id
  481. *
  482. * @param id Id of the particle effect
  483. * @return The particle effect
  484. */
  485. public static ParticleEffect fromId(int id) {
  486. for (Entry<Integer, ParticleEffect> entry : ID_MAP.entrySet()) {
  487. if (entry.getKey() != id) {
  488. continue;
  489. }
  490. return entry.getValue();
  491. }
  492. return null;
  493. }
  494.  
  495. /**
  496. * Determine if water is at a certain location
  497. *
  498. * @param location Location to check
  499. * @return Whether water is at this location or not
  500. */
  501. private static boolean isWater(Location location) {
  502. Material material = location.getBlock().getType();
  503. return material == Material.WATER || material == Material.STATIONARY_WATER;
  504. }
  505.  
  506. /**
  507. * Determine if the distance between @param location and one of the players exceeds 256
  508. *
  509. * @param location Location to check
  510. * @return Whether the distance exceeds 256 or not
  511. */
  512. private static boolean isLongDistance(Location location, List<Player> players) {
  513. String world = location.getWorld().getName();
  514. for (Player player : players) {
  515. Location playerLocation = player.getLocation();
  516. if (!world.equals(playerLocation.getWorld().getName()) || playerLocation.distanceSquared(location) < 65536) {
  517. continue;
  518. }
  519. return true;
  520. }
  521. return false;
  522. }
  523.  
  524. /**
  525. * Determine if the data type for a particle effect is correct
  526. *
  527. * @param effect Particle effect
  528. * @param data Particle data
  529. * @return Whether the data type is correct or not
  530. */
  531. private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) {
  532. return ((effect == BLOCK_CRACK || effect == BLOCK_DUST) && data instanceof BlockData) || (effect == ITEM_CRACK && data instanceof ItemData);
  533. }
  534.  
  535. /**
  536. * Determine if the color type for a particle effect is correct
  537. *
  538. * @param effect Particle effect
  539. * @param color Particle color
  540. * @return Whether the color type is correct or not
  541. */
  542. private static boolean isColorCorrect(ParticleEffect effect, ParticleColor color) {
  543. return ((effect == SPELL_MOB || effect == SPELL_MOB_AMBIENT || effect == REDSTONE) && color instanceof OrdinaryColor) || (effect == NOTE && color instanceof NoteColor);
  544. }
  545.  
  546. /**
  547. * Displays a particle effect which is only visible for all players within a certain range in the world of @param center
  548. *
  549. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  550. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  551. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  552. * @param speed Display speed of the particles
  553. * @param amount Amount of particles
  554. * @param center Center location of the effect
  555. * @param range Range of the visibility
  556. * @throws ParticleVersionException If the particle effect is not supported by the server version
  557. * @throws ParticleDataException If the particle effect requires additional data
  558. * @throws IllegalArgumentException If the particle effect requires water and none is at the center location
  559. * @see ParticlePacket
  560. * @see ParticlePacket#sendTo(Location, double)
  561. */
  562. public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  563. if (!isSupported()) {
  564. throw new ParticleVersionException("This particle effect is not supported by your server version");
  565. }
  566. if (hasProperty(ParticleProperty.REQUIRES_DATA)) {
  567. throw new ParticleDataException("This particle effect requires additional data");
  568. }
  569. if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) {
  570. throw new IllegalArgumentException("There is no water at the center location");
  571. }
  572. new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, null).sendTo(center, range);
  573. }
  574.  
  575. /**
  576. * Displays a particle effect which is only visible for the specified players
  577. *
  578. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  579. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  580. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  581. * @param speed Display speed of the particles
  582. * @param amount Amount of particles
  583. * @param center Center location of the effect
  584. * @param players Receivers of the effect
  585. * @throws ParticleVersionException If the particle effect is not supported by the server version
  586. * @throws ParticleDataException If the particle effect requires additional data
  587. * @throws IllegalArgumentException If the particle effect requires water and none is at the center location
  588. * @see ParticlePacket
  589. * @see ParticlePacket#sendTo(Location, List)
  590. */
  591. public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List<Player> players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  592. if (!isSupported()) {
  593. throw new ParticleVersionException("This particle effect is not supported by your server version");
  594. }
  595. if (hasProperty(ParticleProperty.REQUIRES_DATA)) {
  596. throw new ParticleDataException("This particle effect requires additional data");
  597. }
  598. if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) {
  599. throw new IllegalArgumentException("There is no water at the center location");
  600. }
  601. new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players);
  602. }
  603.  
  604. /**
  605. * Displays a particle effect which is only visible for the specified players
  606. *
  607. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  608. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  609. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  610. * @param speed Display speed of the particles
  611. * @param amount Amount of particles
  612. * @param center Center location of the effect
  613. * @param players Receivers of the effect
  614. * @throws ParticleVersionException If the particle effect is not supported by the server version
  615. * @throws ParticleDataException If the particle effect requires additional data
  616. * @throws IllegalArgumentException If the particle effect requires water and none is at the center location
  617. * @see #display(float, float, float, float, int, Location, List)
  618. */
  619. public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  620. display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players));
  621. }
  622.  
  623. /**
  624. * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center
  625. *
  626. * @param direction Direction of the particle
  627. * @param speed Display speed of the particle
  628. * @param center Center location of the effect
  629. * @param range Range of the visibility
  630. * @throws ParticleVersionException If the particle effect is not supported by the server version
  631. * @throws ParticleDataException If the particle effect requires additional data
  632. * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location
  633. * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData)
  634. * @see ParticlePacket#sendTo(Location, double)
  635. */
  636. public void display(Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  637. if (!isSupported()) {
  638. throw new ParticleVersionException("This particle effect is not supported by your server version");
  639. }
  640. if (hasProperty(ParticleProperty.REQUIRES_DATA)) {
  641. throw new ParticleDataException("This particle effect requires additional data");
  642. }
  643. if (!hasProperty(ParticleProperty.DIRECTIONAL)) {
  644. throw new IllegalArgumentException("This particle effect is not directional");
  645. }
  646. if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) {
  647. throw new IllegalArgumentException("There is no water at the center location");
  648. }
  649. new ParticlePacket(this, direction, speed, range > 256, null).sendTo(center, range);
  650. }
  651.  
  652. /**
  653. * Displays a single particle which flies into a determined direction and is only visible for the specified players
  654. *
  655. * @param direction Direction of the particle
  656. * @param speed Display speed of the particle
  657. * @param center Center location of the effect
  658. * @param players Receivers of the effect
  659. * @throws ParticleVersionException If the particle effect is not supported by the server version
  660. * @throws ParticleDataException If the particle effect requires additional data
  661. * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location
  662. * @see ParticlePacket#ParticlePacket(ParticleEffect, Vector, float, boolean, ParticleData)
  663. * @see ParticlePacket#sendTo(Location, List)
  664. */
  665. public void display(Vector direction, float speed, Location center, List<Player> players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  666. if (!isSupported()) {
  667. throw new ParticleVersionException("This particle effect is not supported by your server version");
  668. }
  669. if (hasProperty(ParticleProperty.REQUIRES_DATA)) {
  670. throw new ParticleDataException("This particle effect requires additional data");
  671. }
  672. if (!hasProperty(ParticleProperty.DIRECTIONAL)) {
  673. throw new IllegalArgumentException("This particle effect is not directional");
  674. }
  675. if (hasProperty(ParticleProperty.REQUIRES_WATER) && !isWater(center)) {
  676. throw new IllegalArgumentException("There is no water at the center location");
  677. }
  678. new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players);
  679. }
  680.  
  681. /**
  682. * Displays a single particle which flies into a determined direction and is only visible for the specified players
  683. *
  684. * @param direction Direction of the particle
  685. * @param speed Display speed of the particle
  686. * @param center Center location of the effect
  687. * @param players Receivers of the effect
  688. * @throws ParticleVersionException If the particle effect is not supported by the server version
  689. * @throws ParticleDataException If the particle effect requires additional data
  690. * @throws IllegalArgumentException If the particle effect is not directional or if it requires water and none is at the center location
  691. * @see #display(Vector, float, Location, List)
  692. */
  693. public void display(Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException, IllegalArgumentException {
  694. display(direction, speed, center, Arrays.asList(players));
  695. }
  696.  
  697. /**
  698. * Displays a single particle which is colored and only visible for all players within a certain range in the world of @param center
  699. *
  700. * @param color Color of the particle
  701. * @param center Center location of the effect
  702. * @param range Range of the visibility
  703. * @throws ParticleVersionException If the particle effect is not supported by the server version
  704. * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
  705. * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean)
  706. * @see ParticlePacket#sendTo(Location, double)
  707. */
  708. public void display(ParticleColor color, Location center, double range) throws ParticleVersionException, ParticleColorException {
  709. if (!isSupported()) {
  710. throw new ParticleVersionException("This particle effect is not supported by your server version");
  711. }
  712. if (!hasProperty(ParticleProperty.COLORABLE)) {
  713. throw new ParticleColorException("This particle effect is not colorable");
  714. }
  715. if (!isColorCorrect(this, color)) {
  716. throw new ParticleColorException("The particle color type is incorrect");
  717. }
  718. new ParticlePacket(this, color, range > 256).sendTo(center, range);
  719. }
  720.  
  721. /**
  722. * Displays a single particle which is colored and only visible for the specified players
  723. *
  724. * @param color Color of the particle
  725. * @param center Center location of the effect
  726. * @param players Receivers of the effect
  727. * @throws ParticleVersionException If the particle effect is not supported by the server version
  728. * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
  729. * @see ParticlePacket#ParticlePacket(ParticleEffect, ParticleColor, boolean)
  730. * @see ParticlePacket#sendTo(Location, List)
  731. */
  732. public void display(ParticleColor color, Location center, List<Player> players) throws ParticleVersionException, ParticleColorException {
  733. if (!isSupported()) {
  734. throw new ParticleVersionException("This particle effect is not supported by your server version");
  735. }
  736. if (!hasProperty(ParticleProperty.COLORABLE)) {
  737. throw new ParticleColorException("This particle effect is not colorable");
  738. }
  739. if (!isColorCorrect(this, color)) {
  740. throw new ParticleColorException("The particle color type is incorrect");
  741. }
  742. new ParticlePacket(this, color, isLongDistance(center, players)).sendTo(center, players);
  743. }
  744.  
  745. /**
  746. * Displays a single particle which is colored and only visible for the specified players
  747. *
  748. * @param color Color of the particle
  749. * @param center Center location of the effect
  750. * @param players Receivers of the effect
  751. * @throws ParticleVersionException If the particle effect is not supported by the server version
  752. * @throws ParticleColorException If the particle effect is not colorable or the color type is incorrect
  753. * @see #display(ParticleColor, Location, List)
  754. */
  755. public void display(ParticleColor color, Location center, Player... players) throws ParticleVersionException, ParticleColorException {
  756. display(color, center, Arrays.asList(players));
  757. }
  758.  
  759. /**
  760. * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center
  761. *
  762. * @param data Data of the effect
  763. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  764. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  765. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  766. * @param speed Display speed of the particles
  767. * @param amount Amount of particles
  768. * @param center Center location of the effect
  769. * @param range Range of the visibility
  770. * @throws ParticleVersionException If the particle effect is not supported by the server version
  771. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  772. * @see ParticlePacket
  773. * @see ParticlePacket#sendTo(Location, double)
  774. */
  775. public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) throws ParticleVersionException, ParticleDataException {
  776. if (!isSupported()) {
  777. throw new ParticleVersionException("This particle effect is not supported by your server version");
  778. }
  779. if (!hasProperty(ParticleProperty.REQUIRES_DATA)) {
  780. throw new ParticleDataException("This particle effect does not require additional data");
  781. }
  782. if (!isDataCorrect(this, data)) {
  783. throw new ParticleDataException("The particle data type is incorrect");
  784. }
  785. new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 256, data).sendTo(center, range);
  786. }
  787.  
  788. /**
  789. * Displays a particle effect which requires additional data and is only visible for the specified players
  790. *
  791. * @param data Data of the effect
  792. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  793. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  794. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  795. * @param speed Display speed of the particles
  796. * @param amount Amount of particles
  797. * @param center Center location of the effect
  798. * @param players Receivers of the effect
  799. * @throws ParticleVersionException If the particle effect is not supported by the server version
  800. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  801. * @see ParticlePacket
  802. * @see ParticlePacket#sendTo(Location, List)
  803. */
  804. public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List<Player> players) throws ParticleVersionException, ParticleDataException {
  805. if (!isSupported()) {
  806. throw new ParticleVersionException("This particle effect is not supported by your server version");
  807. }
  808. if (!hasProperty(ParticleProperty.REQUIRES_DATA)) {
  809. throw new ParticleDataException("This particle effect does not require additional data");
  810. }
  811. if (!isDataCorrect(this, data)) {
  812. throw new ParticleDataException("The particle data type is incorrect");
  813. }
  814. new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players);
  815. }
  816.  
  817. /**
  818. * Displays a particle effect which requires additional data and is only visible for the specified players
  819. *
  820. * @param data Data of the effect
  821. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  822. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  823. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  824. * @param speed Display speed of the particles
  825. * @param amount Amount of particles
  826. * @param center Center location of the effect
  827. * @param players Receivers of the effect
  828. * @throws ParticleVersionException If the particle effect is not supported by the server version
  829. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  830. * @see #display(ParticleData, float, float, float, float, int, Location, List)
  831. */
  832. public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) throws ParticleVersionException, ParticleDataException {
  833. display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players));
  834. }
  835.  
  836. /**
  837. * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center
  838. *
  839. * @param data Data of the effect
  840. * @param direction Direction of the particle
  841. * @param speed Display speed of the particles
  842. * @param center Center location of the effect
  843. * @param range Range of the visibility
  844. * @throws ParticleVersionException If the particle effect is not supported by the server version
  845. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  846. * @see ParticlePacket
  847. * @see ParticlePacket#sendTo(Location, double)
  848. */
  849. public void display(ParticleData data, Vector direction, float speed, Location center, double range) throws ParticleVersionException, ParticleDataException {
  850. if (!isSupported()) {
  851. throw new ParticleVersionException("This particle effect is not supported by your server version");
  852. }
  853. if (!hasProperty(ParticleProperty.REQUIRES_DATA)) {
  854. throw new ParticleDataException("This particle effect does not require additional data");
  855. }
  856. if (!isDataCorrect(this, data)) {
  857. throw new ParticleDataException("The particle data type is incorrect");
  858. }
  859. new ParticlePacket(this, direction, speed, range > 256, data).sendTo(center, range);
  860. }
  861.  
  862. /**
  863. * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players
  864. *
  865. * @param data Data of the effect
  866. * @param direction Direction of the particle
  867. * @param speed Display speed of the particles
  868. * @param center Center location of the effect
  869. * @param players Receivers of the effect
  870. * @throws ParticleVersionException If the particle effect is not supported by the server version
  871. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  872. * @see ParticlePacket
  873. * @see ParticlePacket#sendTo(Location, List)
  874. */
  875. public void display(ParticleData data, Vector direction, float speed, Location center, List<Player> players) throws ParticleVersionException, ParticleDataException {
  876. if (!isSupported()) {
  877. throw new ParticleVersionException("This particle effect is not supported by your server version");
  878. }
  879. if (!hasProperty(ParticleProperty.REQUIRES_DATA)) {
  880. throw new ParticleDataException("This particle effect does not require additional data");
  881. }
  882. if (!isDataCorrect(this, data)) {
  883. throw new ParticleDataException("The particle data type is incorrect");
  884. }
  885. new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players);
  886. }
  887.  
  888. /**
  889. * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players
  890. *
  891. * @param data Data of the effect
  892. * @param direction Direction of the particle
  893. * @param speed Display speed of the particles
  894. * @param center Center location of the effect
  895. * @param players Receivers of the effect
  896. * @throws ParticleVersionException If the particle effect is not supported by the server version
  897. * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect
  898. * @see #display(ParticleData, Vector, float, Location, List)
  899. */
  900. public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) throws ParticleVersionException, ParticleDataException {
  901. display(data, direction, speed, center, Arrays.asList(players));
  902. }
  903.  
  904. /**
  905. * Represents the property of a particle effect
  906. * <p>
  907. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  908. *
  909. * @author DarkBlade12
  910. * @since 1.7
  911. */
  912. public static enum ParticleProperty {
  913. /**
  914. * The particle effect requires water to be displayed
  915. */
  916. REQUIRES_WATER,
  917. /**
  918. * The particle effect requires block or item data to be displayed
  919. */
  920. REQUIRES_DATA,
  921. /**
  922. * The particle effect uses the offsets as direction values
  923. */
  924. DIRECTIONAL,
  925. /**
  926. * The particle effect uses the offsets as color values
  927. */
  928. COLORABLE;
  929. }
  930.  
  931. /**
  932. * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST}
  933. * <p>
  934. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  935. *
  936. * @author DarkBlade12
  937. * @since 1.6
  938. */
  939. public static abstract class ParticleData {
  940. private final Material material;
  941. private final byte data;
  942. private final int[] packetData;
  943.  
  944. /**
  945. * Construct a new particle data
  946. *
  947. * @param material Material of the item/block
  948. * @param data Data value of the item/block
  949. */
  950. @SuppressWarnings("deprecation")
  951. public ParticleData(Material material, byte data) {
  952. this.material = material;
  953. this.data = data;
  954. this.packetData = new int[] { material.getId(), data };
  955. }
  956.  
  957. /**
  958. * Returns the material of this data
  959. *
  960. * @return The material
  961. */
  962. public Material getMaterial() {
  963. return material;
  964. }
  965.  
  966. /**
  967. * Returns the data value of this data
  968. *
  969. * @return The data value
  970. */
  971. public byte getData() {
  972. return data;
  973. }
  974.  
  975. /**
  976. * Returns the data as an int array for packet construction
  977. *
  978. * @return The data for the packet
  979. */
  980. public int[] getPacketData() {
  981. return packetData;
  982. }
  983.  
  984. /**
  985. * Returns the data as a string for pre 1.8 versions
  986. *
  987. * @return The data string for the packet
  988. */
  989. public String getPacketDataString() {
  990. return "_" + packetData[0] + "_" + packetData[1];
  991. }
  992. }
  993.  
  994. /**
  995. * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect
  996. * <p>
  997. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  998. *
  999. * @author DarkBlade12
  1000. * @since 1.6
  1001. */
  1002. public static final class ItemData extends ParticleData {
  1003. /**
  1004. * Construct a new item data
  1005. *
  1006. * @param material Material of the item
  1007. * @param data Data value of the item
  1008. * @see ParticleData#ParticleData(Material, byte)
  1009. */
  1010. public ItemData(Material material, byte data) {
  1011. super(material, data);
  1012. }
  1013. }
  1014.  
  1015. /**
  1016. * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects
  1017. * <p>
  1018. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1019. *
  1020. * @author DarkBlade12
  1021. * @since 1.6
  1022. */
  1023. public static final class BlockData extends ParticleData {
  1024. /**
  1025. * Construct a new block data
  1026. *
  1027. * @param material Material of the block
  1028. * @param data Data value of the block
  1029. * @throws IllegalArgumentException If the material is not a block
  1030. * @see ParticleData#ParticleData(Material, byte)
  1031. */
  1032. public BlockData(Material material, byte data) throws IllegalArgumentException {
  1033. super(material, data);
  1034. if (!material.isBlock()) {
  1035. throw new IllegalArgumentException("The material is not a block");
  1036. }
  1037. }
  1038. }
  1039.  
  1040. /**
  1041. * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT}, {@link ParticleEffect#REDSTONE} and {@link ParticleEffect#NOTE}
  1042. * <p>
  1043. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1044. *
  1045. * @author DarkBlade12
  1046. * @since 1.7
  1047. */
  1048. public static abstract class ParticleColor {
  1049. /**
  1050. * Returns the value for the offsetX field
  1051. *
  1052. * @return The offsetX value
  1053. */
  1054. public abstract float getValueX();
  1055.  
  1056. /**
  1057. * Returns the value for the offsetY field
  1058. *
  1059. * @return The offsetY value
  1060. */
  1061. public abstract float getValueY();
  1062.  
  1063. /**
  1064. * Returns the value for the offsetZ field
  1065. *
  1066. * @return The offsetZ value
  1067. */
  1068. public abstract float getValueZ();
  1069. }
  1070.  
  1071. /**
  1072. * Represents the color for effects like {@link ParticleEffect#SPELL_MOB}, {@link ParticleEffect#SPELL_MOB_AMBIENT} and {@link ParticleEffect#NOTE}
  1073. * <p>
  1074. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1075. *
  1076. * @author DarkBlade12
  1077. * @since 1.7
  1078. */
  1079. public static final class OrdinaryColor extends ParticleColor {
  1080. private final int red;
  1081. private final int green;
  1082. private final int blue;
  1083.  
  1084. /**
  1085. * Construct a new ordinary color
  1086. *
  1087. * @param red Red value of the RGB format
  1088. * @param green Green value of the RGB format
  1089. * @param blue Blue value of the RGB format
  1090. * @throws IllegalArgumentException If one of the values is lower than 0 or higher than 255
  1091. */
  1092. public OrdinaryColor(int red, int green, int blue) throws IllegalArgumentException {
  1093. if (red < 0) {
  1094. throw new IllegalArgumentException("The red value is lower than 0");
  1095. }
  1096. if (red > 255) {
  1097. throw new IllegalArgumentException("The red value is higher than 255");
  1098. }
  1099. this.red = red;
  1100. if (green < 0) {
  1101. throw new IllegalArgumentException("The green value is lower than 0");
  1102. }
  1103. if (green > 255) {
  1104. throw new IllegalArgumentException("The green value is higher than 255");
  1105. }
  1106. this.green = green;
  1107. if (blue < 0) {
  1108. throw new IllegalArgumentException("The blue value is lower than 0");
  1109. }
  1110. if (blue > 255) {
  1111. throw new IllegalArgumentException("The blue value is higher than 255");
  1112. }
  1113. this.blue = blue;
  1114. }
  1115.  
  1116. /**
  1117. * Construct a new ordinary color
  1118. *
  1119. * @param color Bukkit color
  1120. */
  1121. public OrdinaryColor(Color color) {
  1122. this(color.getRed(), color.getGreen(), color.getBlue());
  1123. }
  1124.  
  1125. /**
  1126. * Returns the red value of the RGB format
  1127. *
  1128. * @return The red value
  1129. */
  1130. public int getRed() {
  1131. return red;
  1132. }
  1133.  
  1134. /**
  1135. * Returns the green value of the RGB format
  1136. *
  1137. * @return The green value
  1138. */
  1139. public int getGreen() {
  1140. return green;
  1141. }
  1142.  
  1143. /**
  1144. * Returns the blue value of the RGB format
  1145. *
  1146. * @return The blue value
  1147. */
  1148. public int getBlue() {
  1149. return blue;
  1150. }
  1151.  
  1152. /**
  1153. * Returns the red value divided by 255
  1154. *
  1155. * @return The offsetX value
  1156. */
  1157. @Override
  1158. public float getValueX() {
  1159. return (float) red / 255F;
  1160. }
  1161.  
  1162. /**
  1163. * Returns the green value divided by 255
  1164. *
  1165. * @return The offsetY value
  1166. */
  1167. @Override
  1168. public float getValueY() {
  1169. return (float) green / 255F;
  1170. }
  1171.  
  1172. /**
  1173. * Returns the blue value divided by 255
  1174. *
  1175. * @return The offsetZ value
  1176. */
  1177. @Override
  1178. public float getValueZ() {
  1179. return (float) blue / 255F;
  1180. }
  1181. }
  1182.  
  1183. /**
  1184. * Represents the color for the {@link ParticleEffect#NOTE} effect
  1185. * <p>
  1186. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1187. *
  1188. * @author DarkBlade12
  1189. * @since 1.7
  1190. */
  1191. public static final class NoteColor extends ParticleColor {
  1192. private final int note;
  1193.  
  1194. /**
  1195. * Construct a new note color
  1196. *
  1197. * @param note Note id which determines color
  1198. * @throws IllegalArgumentException If the note value is lower than 0 or higher than 24
  1199. */
  1200. public NoteColor(int note) throws IllegalArgumentException {
  1201. if (note < 0) {
  1202. throw new IllegalArgumentException("The note value is lower than 0");
  1203. }
  1204. if (note > 24) {
  1205. throw new IllegalArgumentException("The note value is higher than 24");
  1206. }
  1207. this.note = note;
  1208. }
  1209.  
  1210. /**
  1211. * Returns the note value divided by 24
  1212. *
  1213. * @return The offsetX value
  1214. */
  1215. @Override
  1216. public float getValueX() {
  1217. return (float) note / 24F;
  1218. }
  1219.  
  1220. /**
  1221. * Returns zero because the offsetY value is unused
  1222. *
  1223. * @return zero
  1224. */
  1225. @Override
  1226. public float getValueY() {
  1227. return 0;
  1228. }
  1229.  
  1230. /**
  1231. * Returns zero because the offsetZ value is unused
  1232. *
  1233. * @return zero
  1234. */
  1235. @Override
  1236. public float getValueZ() {
  1237. return 0;
  1238. }
  1239.  
  1240. }
  1241.  
  1242. /**
  1243. * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is incorrect
  1244. * <p>
  1245. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1246. *
  1247. * @author DarkBlade12
  1248. * @since 1.6
  1249. */
  1250. private static final class ParticleDataException extends RuntimeException {
  1251. private static final long serialVersionUID = 3203085387160737484L;
  1252.  
  1253. /**
  1254. * Construct a new particle data exception
  1255. *
  1256. * @param message Message that will be logged
  1257. */
  1258. public ParticleDataException(String message) {
  1259. super(message);
  1260. }
  1261. }
  1262.  
  1263. /**
  1264. * Represents a runtime exception that is thrown either if the displayed particle effect is not colorable or if the particle color type is incorrect
  1265. * <p>
  1266. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1267. *
  1268. * @author DarkBlade12
  1269. * @since 1.7
  1270. */
  1271. private static final class ParticleColorException extends RuntimeException {
  1272. private static final long serialVersionUID = 3203085387160737484L;
  1273.  
  1274. /**
  1275. * Construct a new particle color exception
  1276. *
  1277. * @param message Message that will be logged
  1278. */
  1279. public ParticleColorException(String message) {
  1280. super(message);
  1281. }
  1282. }
  1283.  
  1284. /**
  1285. * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version
  1286. * <p>
  1287. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1288. *
  1289. * @author DarkBlade12
  1290. * @since 1.6
  1291. */
  1292. private static final class ParticleVersionException extends RuntimeException {
  1293. private static final long serialVersionUID = 3203085387160737484L;
  1294.  
  1295. /**
  1296. * Construct a new particle version exception
  1297. *
  1298. * @param message Message that will be logged
  1299. */
  1300. public ParticleVersionException(String message) {
  1301. super(message);
  1302. }
  1303. }
  1304.  
  1305. /**
  1306. * Represents a particle effect packet with all attributes which is used for sending packets to the players
  1307. * <p>
  1308. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1309. *
  1310. * @author DarkBlade12
  1311. * @since 1.5
  1312. */
  1313. public static final class ParticlePacket {
  1314. private static int version;
  1315. private static Class<?> enumParticle;
  1316. private static Constructor<?> packetConstructor;
  1317. private static Method getHandle;
  1318. private static Field playerConnection;
  1319. private static Method sendPacket;
  1320. private static boolean initialized;
  1321. private final ParticleEffect effect;
  1322. private float offsetX;
  1323. private final float offsetY;
  1324. private final float offsetZ;
  1325. private final float speed;
  1326. private final int amount;
  1327. private final boolean longDistance;
  1328. private final ParticleData data;
  1329. private Object packet;
  1330.  
  1331. /**
  1332. * Construct a new particle packet
  1333. *
  1334. * @param effect Particle effect
  1335. * @param offsetX Maximum distance particles can fly away from the center on the x-axis
  1336. * @param offsetY Maximum distance particles can fly away from the center on the y-axis
  1337. * @param offsetZ Maximum distance particles can fly away from the center on the z-axis
  1338. * @param speed Display speed of the particles
  1339. * @param amount Amount of particles
  1340. * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536
  1341. * @param data Data of the effect
  1342. * @throws IllegalArgumentException If the speed or amount is lower than 0
  1343. * @see #initialize()
  1344. */
  1345. public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) throws IllegalArgumentException {
  1346. initialize();
  1347. if (speed < 0) {
  1348. throw new IllegalArgumentException("The speed is lower than 0");
  1349. }
  1350. if (amount < 0) {
  1351. throw new IllegalArgumentException("The amount is lower than 0");
  1352. }
  1353. this.effect = effect;
  1354. this.offsetX = offsetX;
  1355. this.offsetY = offsetY;
  1356. this.offsetZ = offsetZ;
  1357. this.speed = speed;
  1358. this.amount = amount;
  1359. this.longDistance = longDistance;
  1360. this.data = data;
  1361. }
  1362.  
  1363. /**
  1364. * Construct a new particle packet of a single particle flying into a determined direction
  1365. *
  1366. * @param effect Particle effect
  1367. * @param direction Direction of the particle
  1368. * @param speed Display speed of the particle
  1369. * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536
  1370. * @param data Data of the effect
  1371. * @throws IllegalArgumentException If the speed is lower than 0
  1372. * @see #ParticleEffect(ParticleEffect, float, float, float, float, int, boolean, ParticleData)
  1373. */
  1374. public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) throws IllegalArgumentException {
  1375. this(effect, (float) direction.getX(), (float) direction.getY(), (float) direction.getZ(), speed, 0, longDistance, data);
  1376. }
  1377.  
  1378. /**
  1379. * Construct a new particle packet of a single colored particle
  1380. *
  1381. * @param effect Particle effect
  1382. * @param color Color of the particle
  1383. * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536
  1384. * @see #ParticleEffect(ParticleEffect, float, float, float, float, int, boolean, ParticleData)
  1385. */
  1386. public ParticlePacket(ParticleEffect effect, ParticleColor color, boolean longDistance) {
  1387. this(effect, color.getValueX(), color.getValueY(), color.getValueZ(), 1, 0, longDistance, null);
  1388. if (effect == ParticleEffect.REDSTONE && color instanceof OrdinaryColor && ((OrdinaryColor) color).getRed() == 0) {
  1389. offsetX = (float) 1 / 255F;
  1390. }
  1391. }
  1392.  
  1393. /**
  1394. * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to <code>true</code> if it succeeds
  1395. * <p>
  1396. * <b>Note:</b> These fields only have to be initialized once, so it will return if {@link #initialized} is already set to <code>true</code>
  1397. *
  1398. * @throws VersionIncompatibleException if your bukkit version is not supported by this library
  1399. */
  1400. public static void initialize() throws VersionIncompatibleException {
  1401. if (initialized) {
  1402. return;
  1403. }
  1404. try {
  1405. version = Integer.parseInt(Character.toString(PackageType.getServerVersion().charAt(3)));
  1406. if (version > 7) {
  1407. enumParticle = PackageType.MINECRAFT_SERVER.getClass("EnumParticle");
  1408. }
  1409. Class<?> packetClass = PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles");
  1410. packetConstructor = ReflectionUtils.getConstructor(packetClass);
  1411. getHandle = ReflectionUtils.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
  1412. playerConnection = ReflectionUtils.getField("EntityPlayer", PackageType.MINECRAFT_SERVER, false, "playerConnection");
  1413. sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", PackageType.MINECRAFT_SERVER.getClass("Packet"));
  1414. } catch (Exception exception) {
  1415. throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception);
  1416. }
  1417. initialized = true;
  1418. }
  1419.  
  1420. /**
  1421. * Returns the version of your server (1.x)
  1422. *
  1423. * @return The version number
  1424. */
  1425. public static int getVersion() {
  1426. if (!initialized) {
  1427. initialize();
  1428. }
  1429. return version;
  1430. }
  1431.  
  1432. /**
  1433. * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized
  1434. *
  1435. * @return Whether these fields are initialized or not
  1436. * @see #initialize()
  1437. */
  1438. public static boolean isInitialized() {
  1439. return initialized;
  1440. }
  1441.  
  1442. /**
  1443. * Initializes {@link #packet} with all set values
  1444. *
  1445. * @param center Center location of the effect
  1446. * @throws PacketInstantiationException If instantion fails due to an unknown error
  1447. */
  1448. private void initializePacket(Location center) throws PacketInstantiationException {
  1449. if (packet != null) {
  1450. return;
  1451. }
  1452. try {
  1453. packet = packetConstructor.newInstance();
  1454. if (version < 8) {
  1455. String name = effect.getName();
  1456. if (data != null) {
  1457. name += data.getPacketDataString();
  1458. }
  1459. ReflectionUtils.setValue(packet, true, "a", name);
  1460. } else {
  1461. ReflectionUtils.setValue(packet, true, "a", enumParticle.getEnumConstants()[effect.getId()]);
  1462. ReflectionUtils.setValue(packet, true, "j", longDistance);
  1463. if (data != null) {
  1464. int[] packetData = data.getPacketData();
  1465. ReflectionUtils.setValue(packet, true, "k", effect == ParticleEffect.ITEM_CRACK ? packetData : new int[] { packetData[0] | (packetData[1] << 12) });
  1466. }
  1467. }
  1468. ReflectionUtils.setValue(packet, true, "b", (float) center.getX());
  1469. ReflectionUtils.setValue(packet, true, "c", (float) center.getY());
  1470. ReflectionUtils.setValue(packet, true, "d", (float) center.getZ());
  1471. ReflectionUtils.setValue(packet, true, "e", offsetX);
  1472. ReflectionUtils.setValue(packet, true, "f", offsetY);
  1473. ReflectionUtils.setValue(packet, true, "g", offsetZ);
  1474. ReflectionUtils.setValue(packet, true, "h", speed);
  1475. ReflectionUtils.setValue(packet, true, "i", amount);
  1476. } catch (Exception exception) {
  1477. throw new PacketInstantiationException("Packet instantiation failed", exception);
  1478. }
  1479. }
  1480.  
  1481. /**
  1482. * Sends the packet to a single player and caches it
  1483. *
  1484. * @param center Center location of the effect
  1485. * @param player Receiver of the packet
  1486. * @throws PacketInstantiationException If instantion fails due to an unknown error
  1487. * @throws PacketSendingException If sending fails due to an unknown error
  1488. * @see #initializePacket(Location)
  1489. */
  1490. public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException {
  1491. initializePacket(center);
  1492. try {
  1493. sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet);
  1494. } catch (Exception exception) {
  1495. throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception);
  1496. }
  1497. }
  1498.  
  1499. /**
  1500. * Sends the packet to all players in the list
  1501. *
  1502. * @param center Center location of the effect
  1503. * @param players Receivers of the packet
  1504. * @throws IllegalArgumentException If the player list is empty
  1505. * @see #sendTo(Location center, Player player)
  1506. */
  1507. public void sendTo(Location center, List<Player> players) throws IllegalArgumentException {
  1508. if (players.isEmpty()) {
  1509. throw new IllegalArgumentException("The player list is empty");
  1510. }
  1511. for (Player player : players) {
  1512. sendTo(center, player);
  1513. }
  1514. }
  1515.  
  1516. /**
  1517. * Sends the packet to all players in a certain range
  1518. *
  1519. * @param center Center location of the effect
  1520. * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types)
  1521. * @throws IllegalArgumentException If the range is lower than 1
  1522. * @see #sendTo(Location center, Player player)
  1523. */
  1524. public void sendTo(Location center, double range) throws IllegalArgumentException {
  1525. if (range < 1) {
  1526. throw new IllegalArgumentException("The range is lower than 1");
  1527. }
  1528. String worldName = center.getWorld().getName();
  1529. double squared = range * range;
  1530. for (Player player : Bukkit.getOnlinePlayers()) {
  1531. if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) {
  1532. continue;
  1533. }
  1534. sendTo(center, player);
  1535. }
  1536. }
  1537.  
  1538. /**
  1539. * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library
  1540. * <p>
  1541. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1542. *
  1543. * @author DarkBlade12
  1544. * @since 1.5
  1545. */
  1546. private static final class VersionIncompatibleException extends RuntimeException {
  1547. private static final long serialVersionUID = 3203085387160737484L;
  1548.  
  1549. /**
  1550. * Construct a new version incompatible exception
  1551. *
  1552. * @param message Message that will be logged
  1553. * @param cause Cause of the exception
  1554. */
  1555. public VersionIncompatibleException(String message, Throwable cause) {
  1556. super(message, cause);
  1557. }
  1558. }
  1559.  
  1560. /**
  1561. * Represents a runtime exception that is thrown if packet instantiation fails
  1562. * <p>
  1563. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1564. *
  1565. * @author DarkBlade12
  1566. * @since 1.4
  1567. */
  1568. private static final class PacketInstantiationException extends RuntimeException {
  1569. private static final long serialVersionUID = 3203085387160737484L;
  1570.  
  1571. /**
  1572. * Construct a new packet instantiation exception
  1573. *
  1574. * @param message Message that will be logged
  1575. * @param cause Cause of the exception
  1576. */
  1577. public PacketInstantiationException(String message, Throwable cause) {
  1578. super(message, cause);
  1579. }
  1580. }
  1581.  
  1582. /**
  1583. * Represents a runtime exception that is thrown if packet sending fails
  1584. * <p>
  1585. * This class is part of the <b>ParticleEffect Library</b> and follows the same usage conditions
  1586. *
  1587. * @author DarkBlade12
  1588. * @since 1.4
  1589. */
  1590. private static final class PacketSendingException extends RuntimeException {
  1591. private static final long serialVersionUID = 3203085387160737484L;
  1592.  
  1593. /**
  1594. * Construct a new packet sending exception
  1595. *
  1596. * @param message Message that will be logged
  1597. * @param cause Cause of the exception
  1598. */
  1599. public PacketSendingException(String message, Throwable cause) {
  1600. super(message, cause);
  1601. }
  1602. }
  1603. }
  1604. }
  1605.  
  1606.  
  1607.  
  1608.  
  1609.  
  1610. package org.kcpdev.framework.particles;
  1611.  
  1612. import java.lang.reflect.Constructor;
  1613. import java.lang.reflect.Field;
  1614. import java.lang.reflect.InvocationTargetException;
  1615. import java.lang.reflect.Method;
  1616. import java.util.HashMap;
  1617. import java.util.Map;
  1618.  
  1619. import org.bukkit.Bukkit;
  1620.  
  1621. /**
  1622. * <b>ReflectionUtils</b>
  1623. * <p>
  1624. * This class provides useful methods which makes dealing with reflection much easier, especially when working with Bukkit
  1625. * <p>
  1626. * You are welcome to use it, modify it and redistribute it under the following conditions:
  1627. * <ul>
  1628. * <li>Don't claim this class as your own
  1629. * <li>Don't remove this disclaimer
  1630. * </ul>
  1631. * <p>
  1632. * <i>It would be nice if you provide credit to me if you use this class in a published project</i>
  1633. *
  1634. * @author DarkBlade12
  1635. * @version 1.1
  1636. */
  1637. public final class ReflectionUtils {
  1638. // Prevent accidental construction
  1639. private ReflectionUtils() {}
  1640.  
  1641. /**
  1642. * Returns the constructor of a given class with the given parameter types
  1643. *
  1644. * @param clazz Target class
  1645. * @param parameterTypes Parameter types of the desired constructor
  1646. * @return The constructor of the target class with the specified parameter types
  1647. * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found
  1648. * @see DataType
  1649. * @see DataType#getPrimitive(Class[])
  1650. * @see DataType#compare(Class[], Class[])
  1651. */
  1652. public static Constructor<?> getConstructor(Class<?> clazz, Class<?>... parameterTypes) throws NoSuchMethodException {
  1653. Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
  1654. for (Constructor<?> constructor : clazz.getConstructors()) {
  1655. if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) {
  1656. continue;
  1657. }
  1658. return constructor;
  1659. }
  1660. throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types");
  1661. }
  1662.  
  1663. /**
  1664. * Returns the constructor of a desired class with the given parameter types
  1665. *
  1666. * @param className Name of the desired target class
  1667. * @param packageType Package where the desired target class is located
  1668. * @param parameterTypes Parameter types of the desired constructor
  1669. * @return The constructor of the desired target class with the specified parameter types
  1670. * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found
  1671. * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1672. * @see #getClass(String, PackageType)
  1673. * @see #getConstructor(Class, Class...)
  1674. */
  1675. public static Constructor<?> getConstructor(String className, PackageType packageType, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
  1676. return getConstructor(packageType.getClass(className), parameterTypes);
  1677. }
  1678.  
  1679. /**
  1680. * Returns an instance of a class with the given arguments
  1681. *
  1682. * @param clazz Target class
  1683. * @param arguments Arguments which are used to construct an object of the target class
  1684. * @return The instance of the target class with the specified arguments
  1685. * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances
  1686. * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances
  1687. * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments)
  1688. * @throws InvocationTargetException If the desired constructor cannot be invoked
  1689. * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found
  1690. */
  1691. public static Object instantiateObject(Class<?> clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
  1692. return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments);
  1693. }
  1694.  
  1695. /**
  1696. * Returns an instance of a desired class with the given arguments
  1697. *
  1698. * @param className Name of the desired target class
  1699. * @param packageType Package where the desired target class is located
  1700. * @param arguments Arguments which are used to construct an object of the desired target class
  1701. * @return The instance of the desired target class with the specified arguments
  1702. * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances
  1703. * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances
  1704. * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments)
  1705. * @throws InvocationTargetException If the desired constructor cannot be invoked
  1706. * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found
  1707. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1708. * @see #getClass(String, PackageType)
  1709. * @see #instantiateObject(Class, Object...)
  1710. */
  1711. public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
  1712. return instantiateObject(packageType.getClass(className), arguments);
  1713. }
  1714.  
  1715. /**
  1716. * Returns a method of a class with the given parameter types
  1717. *
  1718. * @param clazz Target class
  1719. * @param methodName Name of the desired method
  1720. * @param parameterTypes Parameter types of the desired method
  1721. * @return The method of the target class with the specified name and parameter types
  1722. * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found
  1723. * @see DataType#getPrimitive(Class[])
  1724. * @see DataType#compare(Class[], Class[])
  1725. */
  1726. public static Method getMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
  1727. Class<?>[] primitiveTypes = DataType.getPrimitive(parameterTypes);
  1728. for (Method method : clazz.getMethods()) {
  1729. if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) {
  1730. continue;
  1731. }
  1732. return method;
  1733. }
  1734. throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types");
  1735. }
  1736.  
  1737. /**
  1738. * Returns a method of a desired class with the given parameter types
  1739. *
  1740. * @param className Name of the desired target class
  1741. * @param packageType Package where the desired target class is located
  1742. * @param methodName Name of the desired method
  1743. * @param parameterTypes Parameter types of the desired method
  1744. * @return The method of the desired target class with the specified name and parameter types
  1745. * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found
  1746. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1747. * @see #getClass(String, PackageType)
  1748. * @see #getMethod(Class, String, Class...)
  1749. */
  1750. public static Method getMethod(String className, PackageType packageType, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
  1751. return getMethod(packageType.getClass(className), methodName, parameterTypes);
  1752. }
  1753.  
  1754. /**
  1755. * Invokes a method on an object with the given arguments
  1756. *
  1757. * @param instance Target object
  1758. * @param methodName Name of the desired method
  1759. * @param arguments Arguments which are used to invoke the desired method
  1760. * @return The result of invoking the desired method on the target object
  1761. * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
  1762. * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
  1763. * @throws InvocationTargetException If the desired method cannot be invoked on the target object
  1764. * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found
  1765. * @see #getMethod(Class, String, Class...)
  1766. * @see DataType#getPrimitive(Object[])
  1767. */
  1768. public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
  1769. return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
  1770. }
  1771.  
  1772. /**
  1773. * Invokes a method of the target class on an object with the given arguments
  1774. *
  1775. * @param instance Target object
  1776. * @param clazz Target class
  1777. * @param methodName Name of the desired method
  1778. * @param arguments Arguments which are used to invoke the desired method
  1779. * @return The result of invoking the desired method on the target object
  1780. * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
  1781. * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
  1782. * @throws InvocationTargetException If the desired method cannot be invoked on the target object
  1783. * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found
  1784. * @see #getMethod(Class, String, Class...)
  1785. * @see DataType#getPrimitive(Object[])
  1786. */
  1787. public static Object invokeMethod(Object instance, Class<?> clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
  1788. return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments);
  1789. }
  1790.  
  1791. /**
  1792. * Invokes a method of a desired class on an object with the given arguments
  1793. *
  1794. * @param instance Target object
  1795. * @param className Name of the desired target class
  1796. * @param packageType Package where the desired target class is located
  1797. * @param methodName Name of the desired method
  1798. * @param arguments Arguments which are used to invoke the desired method
  1799. * @return The result of invoking the desired method on the target object
  1800. * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances
  1801. * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments)
  1802. * @throws InvocationTargetException If the desired method cannot be invoked on the target object
  1803. * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found
  1804. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1805. * @see #getClass(String, PackageType)
  1806. * @see #invokeMethod(Object, Class, String, Object...)
  1807. */
  1808. public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
  1809. return invokeMethod(instance, packageType.getClass(className), methodName, arguments);
  1810. }
  1811.  
  1812. /**
  1813. * Returns a field of the target class with the given name
  1814. *
  1815. * @param clazz Target class
  1816. * @param declared Whether the desired field is declared or not
  1817. * @param fieldName Name of the desired field
  1818. * @return The field of the target class with the specified name
  1819. * @throws NoSuchFieldException If the desired field of the given class cannot be found
  1820. * @throws SecurityException If the desired field cannot be made accessible
  1821. */
  1822. public static Field getField(Class<?> clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException {
  1823. Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName);
  1824. field.setAccessible(true);
  1825. return field;
  1826. }
  1827.  
  1828. /**
  1829. * Returns a field of a desired class with the given name
  1830. *
  1831. * @param className Name of the desired target class
  1832. * @param packageType Package where the desired target class is located
  1833. * @param declared Whether the desired field is declared or not
  1834. * @param fieldName Name of the desired field
  1835. * @return The field of the desired target class with the specified name
  1836. * @throws NoSuchFieldException If the desired field of the desired class cannot be found
  1837. * @throws SecurityException If the desired field cannot be made accessible
  1838. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1839. * @see #getField(Class, boolean, String)
  1840. */
  1841. public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException {
  1842. return getField(packageType.getClass(className), declared, fieldName);
  1843. }
  1844.  
  1845. /**
  1846. * Returns the value of a field of the given class of an object
  1847. *
  1848. * @param instance Target object
  1849. * @param clazz Target class
  1850. * @param declared Whether the desired field is declared or not
  1851. * @param fieldName Name of the desired field
  1852. * @return The value of field of the target object
  1853. * @throws IllegalArgumentException If the target object does not feature the desired field
  1854. * @throws IllegalAccessException If the desired field cannot be accessed
  1855. * @throws NoSuchFieldException If the desired field of the target class cannot be found
  1856. * @throws SecurityException If the desired field cannot be made accessible
  1857. * @see #getField(Class, boolean, String)
  1858. */
  1859. public static Object getValue(Object instance, Class<?> clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
  1860. return getField(clazz, declared, fieldName).get(instance);
  1861. }
  1862.  
  1863. /**
  1864. * Returns the value of a field of a desired class of an object
  1865. *
  1866. * @param instance Target object
  1867. * @param className Name of the desired target class
  1868. * @param packageType Package where the desired target class is located
  1869. * @param declared Whether the desired field is declared or not
  1870. * @param fieldName Name of the desired field
  1871. * @return The value of field of the target object
  1872. * @throws IllegalArgumentException If the target object does not feature the desired field
  1873. * @throws IllegalAccessException If the desired field cannot be accessed
  1874. * @throws NoSuchFieldException If the desired field of the desired class cannot be found
  1875. * @throws SecurityException If the desired field cannot be made accessible
  1876. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1877. * @see #getValue(Object, Class, boolean, String)
  1878. */
  1879. public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
  1880. return getValue(instance, packageType.getClass(className), declared, fieldName);
  1881. }
  1882.  
  1883. /**
  1884. * Returns the value of a field with the given name of an object
  1885. *
  1886. * @param instance Target object
  1887. * @param declared Whether the desired field is declared or not
  1888. * @param fieldName Name of the desired field
  1889. * @return The value of field of the target object
  1890. * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object)
  1891. * @throws IllegalAccessException If the desired field cannot be accessed
  1892. * @throws NoSuchFieldException If the desired field of the target object cannot be found
  1893. * @throws SecurityException If the desired field cannot be made accessible
  1894. * @see #getValue(Object, Class, boolean, String)
  1895. */
  1896. public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
  1897. return getValue(instance, instance.getClass(), declared, fieldName);
  1898. }
  1899.  
  1900. /**
  1901. * Sets the value of a field of the given class of an object
  1902. *
  1903. * @param instance Target object
  1904. * @param clazz Target class
  1905. * @param declared Whether the desired field is declared or not
  1906. * @param fieldName Name of the desired field
  1907. * @param value New value
  1908. * @throws IllegalArgumentException If the type of the value does not match the type of the desired field
  1909. * @throws IllegalAccessException If the desired field cannot be accessed
  1910. * @throws NoSuchFieldException If the desired field of the target class cannot be found
  1911. * @throws SecurityException If the desired field cannot be made accessible
  1912. * @see #getField(Class, boolean, String)
  1913. */
  1914. public static void setValue(Object instance, Class<?> clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
  1915. getField(clazz, declared, fieldName).set(instance, value);
  1916. }
  1917.  
  1918. /**
  1919. * Sets the value of a field of a desired class of an object
  1920. *
  1921. * @param instance Target object
  1922. * @param className Name of the desired target class
  1923. * @param packageType Package where the desired target class is located
  1924. * @param declared Whether the desired field is declared or not
  1925. * @param fieldName Name of the desired field
  1926. * @param value New value
  1927. * @throws IllegalArgumentException If the type of the value does not match the type of the desired field
  1928. * @throws IllegalAccessException If the desired field cannot be accessed
  1929. * @throws NoSuchFieldException If the desired field of the desired class cannot be found
  1930. * @throws SecurityException If the desired field cannot be made accessible
  1931. * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found
  1932. * @see #setValue(Object, Class, boolean, String, Object)
  1933. */
  1934. public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException {
  1935. setValue(instance, packageType.getClass(className), declared, fieldName, value);
  1936. }
  1937.  
  1938. /**
  1939. * Sets the value of a field with the given name of an object
  1940. *
  1941. * @param instance Target object
  1942. * @param declared Whether the desired field is declared or not
  1943. * @param fieldName Name of the desired field
  1944. * @param value New value
  1945. * @throws IllegalArgumentException If the type of the value does not match the type of the desired field
  1946. * @throws IllegalAccessException If the desired field cannot be accessed
  1947. * @throws NoSuchFieldException If the desired field of the target object cannot be found
  1948. * @throws SecurityException If the desired field cannot be made accessible
  1949. * @see #setValue(Object, Class, boolean, String, Object)
  1950. */
  1951. public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
  1952. setValue(instance, instance.getClass(), declared, fieldName, value);
  1953. }
  1954.  
  1955. /**
  1956. * Represents an enumeration of dynamic packages of NMS and CraftBukkit
  1957. * <p>
  1958. * This class is part of the <b>ReflectionUtils</b> and follows the same usage conditions
  1959. *
  1960. * @author DarkBlade12
  1961. * @since 1.0
  1962. */
  1963. public enum PackageType {
  1964. MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()),
  1965. CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()),
  1966. CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"),
  1967. CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"),
  1968. CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"),
  1969. CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"),
  1970. CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"),
  1971. CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"),
  1972. CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"),
  1973. CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"),
  1974. CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"),
  1975. CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"),
  1976. CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"),
  1977. CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"),
  1978. CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"),
  1979. CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"),
  1980. CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"),
  1981. CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"),
  1982. CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"),
  1983. CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util");
  1984.  
  1985. private final String path;
  1986.  
  1987. /**
  1988. * Construct a new package type
  1989. *
  1990. * @param path Path of the package
  1991. */
  1992. private PackageType(String path) {
  1993. this.path = path;
  1994. }
  1995.  
  1996. /**
  1997. * Construct a new package type
  1998. *
  1999. * @param parent Parent package of the package
  2000. * @param path Path of the package
  2001. */
  2002. private PackageType(PackageType parent, String path) {
  2003. this(parent + "." + path);
  2004. }
  2005.  
  2006. /**
  2007. * Returns the path of this package type
  2008. *
  2009. * @return The path
  2010. */
  2011. public String getPath() {
  2012. return path;
  2013. }
  2014.  
  2015. /**
  2016. * Returns the class with the given name
  2017. *
  2018. * @param className Name of the desired class
  2019. * @return The class with the specified name
  2020. * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found
  2021. */
  2022. public Class<?> getClass(String className) throws ClassNotFoundException {
  2023. return Class.forName(this + "." + className);
  2024. }
  2025.  
  2026. // Override for convenience
  2027. @Override
  2028. public String toString() {
  2029. return path;
  2030. }
  2031.  
  2032. /**
  2033. * Returns the version of your server
  2034. *
  2035. * @return The server version
  2036. */
  2037. public static String getServerVersion() {
  2038. return Bukkit.getServer().getClass().getPackage().getName().substring(23);
  2039. }
  2040. }
  2041.  
  2042. /**
  2043. * Represents an enumeration of Java data types with corresponding classes
  2044. * <p>
  2045. * This class is part of the <b>ReflectionUtils</b> and follows the same usage conditions
  2046. *
  2047. * @author DarkBlade12
  2048. * @since 1.0
  2049. */
  2050. public enum DataType {
  2051. BYTE(byte.class, Byte.class),
  2052. SHORT(short.class, Short.class),
  2053. INTEGER(int.class, Integer.class),
  2054. LONG(long.class, Long.class),
  2055. CHARACTER(char.class, Character.class),
  2056. FLOAT(float.class, Float.class),
  2057. DOUBLE(double.class, Double.class),
  2058. BOOLEAN(boolean.class, Boolean.class);
  2059.  
  2060. private static final Map<Class<?>, DataType> CLASS_MAP = new HashMap<Class<?>, DataType>();
  2061. private final Class<?> primitive;
  2062. private final Class<?> reference;
  2063.  
  2064. // Initialize map for quick class lookup
  2065. static {
  2066. for (DataType type : values()) {
  2067. CLASS_MAP.put(type.primitive, type);
  2068. CLASS_MAP.put(type.reference, type);
  2069. }
  2070. }
  2071.  
  2072. /**
  2073. * Construct a new data type
  2074. *
  2075. * @param primitive Primitive class of this data type
  2076. * @param reference Reference class of this data type
  2077. */
  2078. private DataType(Class<?> primitive, Class<?> reference) {
  2079. this.primitive = primitive;
  2080. this.reference = reference;
  2081. }
  2082.  
  2083. /**
  2084. * Returns the primitive class of this data type
  2085. *
  2086. * @return The primitive class
  2087. */
  2088. public Class<?> getPrimitive() {
  2089. return primitive;
  2090. }
  2091.  
  2092. /**
  2093. * Returns the reference class of this data type
  2094. *
  2095. * @return The reference class
  2096. */
  2097. public Class<?> getReference() {
  2098. return reference;
  2099. }
  2100.  
  2101. /**
  2102. * Returns the data type with the given primitive/reference class
  2103. *
  2104. * @param clazz Primitive/Reference class of the data type
  2105. * @return The data type
  2106. */
  2107. public static DataType fromClass(Class<?> clazz) {
  2108. return CLASS_MAP.get(clazz);
  2109. }
  2110.  
  2111. /**
  2112. * Returns the primitive class of the data type with the given reference class
  2113. *
  2114. * @param clazz Reference class of the data type
  2115. * @return The primitive class
  2116. */
  2117. public static Class<?> getPrimitive(Class<?> clazz) {
  2118. DataType type = fromClass(clazz);
  2119. return type == null ? clazz : type.getPrimitive();
  2120. }
  2121.  
  2122. /**
  2123. * Returns the reference class of the data type with the given primitive class
  2124. *
  2125. * @param clazz Primitive class of the data type
  2126. * @return The reference class
  2127. */
  2128. public static Class<?> getReference(Class<?> clazz) {
  2129. DataType type = fromClass(clazz);
  2130. return type == null ? clazz : type.getReference();
  2131. }
  2132.  
  2133. /**
  2134. * Returns the primitive class array of the given class array
  2135. *
  2136. * @param classes Given class array
  2137. * @return The primitive class array
  2138. */
  2139. public static Class<?>[] getPrimitive(Class<?>[] classes) {
  2140. int length = classes == null ? 0 : classes.length;
  2141. Class<?>[] types = new Class<?>[length];
  2142. for (int index = 0; index < length; index++) {
  2143. types[index] = getPrimitive(classes[index]);
  2144. }
  2145. return types;
  2146. }
  2147.  
  2148. /**
  2149. * Returns the reference class array of the given class array
  2150. *
  2151. * @param classes Given class array
  2152. * @return The reference class array
  2153. */
  2154. public static Class<?>[] getReference(Class<?>[] classes) {
  2155. int length = classes == null ? 0 : classes.length;
  2156. Class<?>[] types = new Class<?>[length];
  2157. for (int index = 0; index < length; index++) {
  2158. types[index] = getReference(classes[index]);
  2159. }
  2160. return types;
  2161. }
  2162.  
  2163. /**
  2164. * Returns the primitive class array of the given object array
  2165. *
  2166. * @param object Given object array
  2167. * @return The primitive class array
  2168. */
  2169. public static Class<?>[] getPrimitive(Object[] objects) {
  2170. int length = objects == null ? 0 : objects.length;
  2171. Class<?>[] types = new Class<?>[length];
  2172. for (int index = 0; index < length; index++) {
  2173. types[index] = getPrimitive(objects[index].getClass());
  2174. }
  2175. return types;
  2176. }
  2177.  
  2178. /**
  2179. * Returns the reference class array of the given object array
  2180. *
  2181. * @param object Given object array
  2182. * @return The reference class array
  2183. */
  2184. public static Class<?>[] getReference(Object[] objects) {
  2185. int length = objects == null ? 0 : objects.length;
  2186. Class<?>[] types = new Class<?>[length];
  2187. for (int index = 0; index < length; index++) {
  2188. types[index] = getReference(objects[index].getClass());
  2189. }
  2190. return types;
  2191. }
  2192.  
  2193. /**
  2194. * Compares two class arrays on equivalence
  2195. *
  2196. * @param primary Primary class array
  2197. * @param secondary Class array which is compared to the primary array
  2198. * @return Whether these arrays are equal or not
  2199. */
  2200. public static boolean compare(Class<?>[] primary, Class<?>[] secondary) {
  2201. if (primary == null || secondary == null || primary.length != secondary.length) {
  2202. return false;
  2203. }
  2204. for (int index = 0; index < primary.length; index++) {
  2205. Class<?> primaryClass = primary[index];
  2206. Class<?> secondaryClass = secondary[index];
  2207. if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) {
  2208. continue;
  2209. }
  2210. return false;
  2211. }
  2212. return true;
  2213. }
  2214. }
  2215. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement