|
|
@ -12,40 +12,41 @@ import org.bukkit.Particle; |
|
|
|
import org.bukkit.entity.Entity; |
|
|
|
import org.bukkit.entity.Player; |
|
|
|
|
|
|
|
import lombok.Getter; |
|
|
|
|
|
|
|
@SuppressWarnings({ "unchecked", "rawtypes" }) |
|
|
|
public class ParticleHandler { |
|
|
|
private static Class<?> packetClass = null; |
|
|
|
private static Constructor<?> packetConstructor = null; |
|
|
|
private static Field player_connection = null; |
|
|
|
private static Method player_sendPacket = null; |
|
|
|
private static HashMap<Class<? extends Entity>, Method> handles = new HashMap<Class<? extends Entity>, Method>(); |
|
|
|
private static Field playerCon = null; |
|
|
|
private static Method sendPacket = null; |
|
|
|
private static HashMap<Class<? extends Entity>, Method> handles = new HashMap<>(); |
|
|
|
|
|
|
|
private static Class<Enum> enumParticle = null; |
|
|
|
private static Class<Enum> enump = null; |
|
|
|
|
|
|
|
private ParticleType type; |
|
|
|
@Getter |
|
|
|
private double speed; |
|
|
|
@Getter |
|
|
|
private int count; |
|
|
|
@Getter |
|
|
|
private double radius; |
|
|
|
|
|
|
|
public static void load() { |
|
|
|
String vString = getVersion().replace("v", ""); |
|
|
|
double v = 0; |
|
|
|
if (!vString.isEmpty()) { |
|
|
|
String[] array = vString.split("_"); |
|
|
|
v = Double.parseDouble(array[0] + "." + array[1]); |
|
|
|
String str = getVersion().replace("v", ""); |
|
|
|
double version = 0; |
|
|
|
if (!str.isEmpty()) { |
|
|
|
String[] array = str.split("_"); |
|
|
|
version = Double.parseDouble(array[0] + "." + array[1]); |
|
|
|
} |
|
|
|
try { |
|
|
|
packetClass = getNmsClass("PacketPlayOutWorldParticles"); |
|
|
|
if (v == 1.8) { |
|
|
|
Bukkit.getLogger().info("[ParticleHandler] Hooking into Netty NMS classes"); |
|
|
|
Bukkit.getLogger().info("[ParticleHandler] Version is " + v + " - using packet constructor"); |
|
|
|
enumParticle = (Class<Enum>) getNmsClass("EnumParticle"); |
|
|
|
packetConstructor = packetClass.getDeclaredConstructor(enumParticle, boolean.class, float.class, |
|
|
|
float.class, float.class, float.class, float.class, float.class, float.class, int.class, |
|
|
|
int[].class); |
|
|
|
} else { |
|
|
|
if (version == 1.8) { |
|
|
|
Bukkit.getLogger().info("[ParticleHandler] Version is " + version + " - using packet constructor"); |
|
|
|
enump = (Class<Enum>) getNmsClass("EnumParticle"); |
|
|
|
packetConstructor = getNmsClass("PacketPlayOutWorldParticles").getDeclaredConstructor(enump, |
|
|
|
boolean.class, float.class, float.class, float.class, float.class, float.class, float.class, |
|
|
|
float.class, int.class, int[].class); |
|
|
|
} else |
|
|
|
Bukkit.getLogger().info("[ParticleHandler] Hooking into the new particle system"); |
|
|
|
} |
|
|
|
} catch (Exception ex) { |
|
|
|
ex.printStackTrace(); |
|
|
|
Bukkit.getLogger().severe("[ParticleHandler] Failed to initialize NMS components!"); |
|
|
@ -59,18 +60,6 @@ public class ParticleHandler { |
|
|
|
this.radius = radius; |
|
|
|
} |
|
|
|
|
|
|
|
public double getSpeed() { |
|
|
|
return speed; |
|
|
|
} |
|
|
|
|
|
|
|
public int getCount() { |
|
|
|
return count; |
|
|
|
} |
|
|
|
|
|
|
|
public double getRadius() { |
|
|
|
return radius; |
|
|
|
} |
|
|
|
|
|
|
|
public void sendToLocation(Location location) { |
|
|
|
String vString = getVersion().replace("v", ""); |
|
|
|
double v = 0; |
|
|
@ -78,29 +67,26 @@ public class ParticleHandler { |
|
|
|
String[] array = vString.split("_"); |
|
|
|
v = Double.parseDouble(array[0] + "." + array[1]); |
|
|
|
} |
|
|
|
if (v == 1.8) { |
|
|
|
if (v == 1.8) |
|
|
|
try { |
|
|
|
Object packet = createPacket(location); |
|
|
|
for (Player player : Bukkit.getOnlinePlayers()) { |
|
|
|
for (Player player : Bukkit.getOnlinePlayers()) |
|
|
|
sendPacket(player, packet); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
location.getWorld().spawnParticle(Particle.valueOf(type.getName().toUpperCase()), (float) location.getX(), |
|
|
|
(float) location.getY(), (float) location.getZ(), this.count, (float) this.radius, |
|
|
|
(float) this.radius, (float) this.radius, (float) this.speed); |
|
|
|
} |
|
|
|
else |
|
|
|
location.getWorld().spawnParticle(Particle.valueOf(type.getParticle().toUpperCase()), |
|
|
|
(float) location.getX(), (float) location.getY(), (float) location.getZ(), this.count, |
|
|
|
(float) this.radius, (float) this.radius, (float) this.radius, (float) this.speed); |
|
|
|
} |
|
|
|
|
|
|
|
private Object createPacket(Location location) { |
|
|
|
try { |
|
|
|
if (this.count <= 0) { |
|
|
|
if (this.count <= 0) |
|
|
|
this.count = 1; |
|
|
|
} |
|
|
|
Object packet; |
|
|
|
Object particleType = enumParticle.getEnumConstants()[type.getId()]; |
|
|
|
Object particleType = enump.getEnumConstants()[type.getId()]; |
|
|
|
packet = packetConstructor.newInstance(particleType, true, (float) location.getX(), (float) location.getY(), |
|
|
|
(float) location.getZ(), (float) this.radius, (float) this.radius, (float) this.radius, |
|
|
|
(float) this.speed, this.count, new int[0]); |
|
|
@ -120,15 +106,13 @@ public class ParticleHandler { |
|
|
|
|
|
|
|
private static void sendPacket(Player p, Object packet) throws IllegalArgumentException { |
|
|
|
try { |
|
|
|
if (player_connection == null) { |
|
|
|
player_connection = getHandle(p).getClass().getField("playerConnection"); |
|
|
|
for (Method m : player_connection.get(getHandle(p)).getClass().getMethods()) { |
|
|
|
if (m.getName().equalsIgnoreCase("sendPacket")) { |
|
|
|
player_sendPacket = m; |
|
|
|
if (playerCon == null) { |
|
|
|
playerCon = getHandle(p).getClass().getField("playerConnection"); |
|
|
|
for (Method m : playerCon.get(getHandle(p)).getClass().getMethods()) |
|
|
|
if (m.getName().equalsIgnoreCase("sendPacket")) |
|
|
|
sendPacket = m; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
player_sendPacket.invoke(player_connection.get(getHandle(p)), packet); |
|
|
|
sendPacket.invoke(playerCon.get(getHandle(p)), packet); |
|
|
|
} catch (IllegalAccessException ex) { |
|
|
|
ex.printStackTrace(); |
|
|
|
Bukkit.getLogger().severe("[ParticleHandler] Failed to send packet!"); |
|
|
@ -176,45 +160,60 @@ public class ParticleHandler { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
@Getter |
|
|
|
public enum ParticleType { |
|
|
|
|
|
|
|
EXPLOSION_NORMAL("explode", 0, 17), EXPLOSION_LARGE("largeexplode", 1, 1), |
|
|
|
EXPLOSION_HUGE("hugeexplosion", 2, 0), FIREWORKS_SPARK("fireworksSpark", 3, 2), WATER_BUBBLE("bubble", 4, 3), |
|
|
|
WATER_SPLASH("splash", 5, 21), WATER_WAKE("wake", 6, -1), SUSPENDED("suspended", 7, 4), |
|
|
|
SUSPENDED_DEPTH("depthsuspend", 8, 5), CRIT("crit", 9, 7), CRIT_MAGIC("magicCrit", 10, 8), |
|
|
|
SMOKE_NORMAL("smoke", 11, -1), SMOKE_LARGE("largesmoke", 12, 22), SPELL("spell", 13, 11), |
|
|
|
SPELL_INSTANT("instantSpell", 14, 12), SPELL_MOB("mobSpell", 15, 9), |
|
|
|
SPELL_MOB_AMBIENT("mobSpellAmbient", 16, 10), SPELL_WITCH("witchMagic", 17, 13), |
|
|
|
DRIP_WATER("dripWater", 18, 27), DRIP_LAVA("dripLava", 19, 28), VILLAGER_ANGRY("angryVillager", 20, 31), |
|
|
|
VILLAGER_HAPPY("happyVillager", 21, 32), TOWN_AURA("townaura", 22, 6), NOTE("note", 23, 24), |
|
|
|
PORTAL("portal", 24, 15), ENCHANTMENT_TABLE("enchantmenttable", 25, 16), FLAME("flame", 26, 18), |
|
|
|
LAVA("lava", 27, 19), FOOTSTEP("footstep", 28, 20), CLOUD("cloud", 29, 23), REDSTONE("reddust", 30, 24), |
|
|
|
SNOWBALL("snowballpoof", 31, 25), SNOW_SHOVEL("snowshovel", 32, 28), SLIME("slime", 33, 29), |
|
|
|
HEART("heart", 34, 30), BARRIER("barrier", 35, -1), ITEM_CRACK("iconcrack_", 36, 33), |
|
|
|
BLOCK_CRACK("tilecrack_", 37, 34), BLOCK_DUST("blockdust_", 38, -1), WATER_DROP("droplet", 39, -1), |
|
|
|
ITEM_TAKE("take", 40, -1), MOB_APPEARANCE("mobappearance", 41, -1); |
|
|
|
|
|
|
|
private String name; |
|
|
|
CRIT("crit", 9, 7), |
|
|
|
CRIT_MAGIC("magicCrit", 10, 8), |
|
|
|
SMOKE_NORMAL("smoke", 11, -1), |
|
|
|
SMOKE_LARGE("largesmoke", 12, 22), |
|
|
|
SPELL("spell", 13, 11), |
|
|
|
SPELL_INSTANT("instantSpell", 14, 12), |
|
|
|
SPELL_MOB("mobSpell", 15, 9), |
|
|
|
SPELL_MOB_AMBIENT("mobSpellAmbient", 16, 10), |
|
|
|
SLIME("slime", 33, 29), |
|
|
|
HEART("heart", 34, 30), |
|
|
|
BARRIER("barrier", 35, -1), |
|
|
|
ITEM_CRACK("iconcrack_", 36, 33), |
|
|
|
BLOCK_CRACK("tilecrack_", 37, 34), |
|
|
|
BLOCK_DUST("blockdust_", 38, -1), |
|
|
|
SPELL_WITCH("witchMagic", 17, 13), |
|
|
|
DRIP_WATER("dripWater", 18, 27), |
|
|
|
DRIP_LAVA("dripLava", 19, 28), |
|
|
|
VILLAGER_ANGRY("angryVillager", 20, 31), |
|
|
|
VILLAGER_HAPPY("happyVillager", 21, 32), |
|
|
|
TOWN_AURA("townaura", 22, 6), |
|
|
|
EXPLOSION_NORMAL("explode", 0, 17), |
|
|
|
EXPLOSION_LARGE("largeexplode", 1, 1), |
|
|
|
EXPLOSION_HUGE("hugeexplosion", 2, 0), |
|
|
|
FIREWORKS_SPARK("fireworksSpark", 3, 2), |
|
|
|
WATER_BUBBLE("bubble", 4, 3), |
|
|
|
WATER_SPLASH("splash", 5, 21), |
|
|
|
WATER_WAKE("wake", 6, -1), |
|
|
|
SUSPENDED("suspended", 7, 4), |
|
|
|
SUSPENDED_DEPTH("depthsuspend", 8, 5), |
|
|
|
NOTE("note", 23, 24), |
|
|
|
PORTAL("portal", 24, 15), |
|
|
|
ENCHANTMENT_TABLE("enchantmenttable", 25, 16), |
|
|
|
FLAME("flame", 26, 18), |
|
|
|
LAVA("lava", 27, 19), |
|
|
|
FOOTSTEP("footstep", 28, 20), |
|
|
|
CLOUD("cloud", 29, 23), |
|
|
|
REDSTONE("reddust", 30, 24), |
|
|
|
SNOWBALL("snowballpoof", 31, 25), |
|
|
|
SNOW_SHOVEL("snowshovel", 32, 28), |
|
|
|
WATER_DROP("droplet", 39, -1), |
|
|
|
ITEM_TAKE("take", 40, -1), |
|
|
|
MOB_APPEARANCE("mobappearance", 41, -1); |
|
|
|
|
|
|
|
private String particle; |
|
|
|
private int id; |
|
|
|
private int legacyId; |
|
|
|
private int legId; |
|
|
|
|
|
|
|
ParticleType(String name, int id, int legacyId) { |
|
|
|
this.name = name; |
|
|
|
ParticleType(String particle, int id, int legId) { |
|
|
|
this.particle = particle; |
|
|
|
this.id = id; |
|
|
|
this.legacyId = legacyId; |
|
|
|
} |
|
|
|
|
|
|
|
String getName() { |
|
|
|
return name; |
|
|
|
} |
|
|
|
|
|
|
|
int getId() { |
|
|
|
return id; |
|
|
|
} |
|
|
|
|
|
|
|
int getLegacyId() { |
|
|
|
return legacyId; |
|
|
|
this.legId = legId; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|