diff --git a/api/src/main/java/net/jitse/npclib/hologram/Hologram.java b/api/src/main/java/net/jitse/npclib/hologram/Hologram.java index 1692e74..07248bc 100644 --- a/api/src/main/java/net/jitse/npclib/hologram/Hologram.java +++ b/api/src/main/java/net/jitse/npclib/hologram/Hologram.java @@ -15,66 +15,66 @@ import java.util.List; public class Hologram { + private static final double DELTA = 0.3; + + // Classes: + private static final Class CHAT_COMPONENT_TEXT_CLASS = Reflection.getMinecraftClass("ChatComponentText"); + private static final Class CHAT_BASE_COMPONENT_CLASS = Reflection.getMinecraftClass("IChatBaseComponent"); + private static final Class ENTITY_ARMOR_STAND_CLASS = Reflection.getMinecraftClass("EntityArmorStand"); + private static final Class ENTITY_LIVING_CLASS = Reflection.getMinecraftClass("EntityLiving"); + private static final Class ENTITY_CLASS = Reflection.getMinecraftClass("Entity"); + private static final Class CRAFT_WORLD_CLASS = Reflection.getCraftBukkitClass("CraftWorld"); + private static final Class CRAFT_PLAYER_CLASS = Reflection.getCraftBukkitClass("entity.CraftPlayer"); + private static final Class PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLASS = Reflection.getMinecraftClass( + "PacketPlayOutSpawnEntityLiving"); + private static final Class PACKET_PLAY_OUT_ENTITY_DESTROY_CLASS = Reflection.getMinecraftClass( + "PacketPlayOutEntityDestroy"); + private static final Class PACKET_PLAY_OUT_ENTITY_METADATA_CLASS = Reflection.getMinecraftClass( + "PacketPlayOutEntityMetadata"); + private static final Class DATAWATCHER_CLASS = Reflection.getMinecraftClass("DataWatcher"); + private static final Class ENTITY_PLAYER_CLASS = Reflection.getMinecraftClass("EntityPlayer"); + private static final Class PLAYER_CONNECTION_CLASS = Reflection.getMinecraftClass("PlayerConnection"); + private static final Class PACKET_CLASS = Reflection.getMinecraftClass("Packet"); + + // Constructors: + private static final Reflection.ConstructorInvoker CHAT_COMPONENT_TEXT_CONSTRUCTOR = Reflection + .getConstructor(CHAT_COMPONENT_TEXT_CLASS, String.class); + private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CONSTRUCTOR = Reflection + .getConstructor(PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLASS, ENTITY_LIVING_CLASS); + private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_ENTITY_DESTROY_CONSTRUCTOR = Reflection + .getConstructor(PACKET_PLAY_OUT_ENTITY_DESTROY_CLASS, int[].class); + private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_ENTITY_METADATA_CONSTRUCTOR = Reflection + .getConstructor(PACKET_PLAY_OUT_ENTITY_METADATA_CLASS, int.class, DATAWATCHER_CLASS, boolean.class); + + // Fields: + private static final Reflection.FieldAccessor PLAYER_CONNECTION_FIELD = Reflection.getField(ENTITY_PLAYER_CLASS, + "playerConnection", PLAYER_CONNECTION_CLASS); + + // Methods: + private static final Reflection.MethodInvoker SET_LOCATION_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "setLocation", double.class, double.class, double.class, float.class, float.class); + private static final Reflection.MethodInvoker SET_SMALL_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "setSmall", boolean.class); + private static final Reflection.MethodInvoker SET_INVISIBLE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "setInvisible", boolean.class); + private static final Reflection.MethodInvoker SET_BASE_PLATE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "setBasePlate", boolean.class); + private static final Reflection.MethodInvoker SET_ARMS_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "setArms", boolean.class); + private static final Reflection.MethodInvoker PLAYER_GET_HANDLE_METHOD = Reflection.getMethod(CRAFT_PLAYER_CLASS, + "getHandle"); + private static final Reflection.MethodInvoker SEND_PACKET_METHOD = Reflection.getMethod(PLAYER_CONNECTION_CLASS, + "sendPacket", PACKET_CLASS); + private static final Reflection.MethodInvoker GET_ID_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, + "getId"); + private static final Reflection.MethodInvoker GET_DATAWATCHER_METHOD = Reflection.getMethod(ENTITY_CLASS, + "getDataWatcher"); + private final List armorStands = new ArrayList<>(); private final List showPackets = new ArrayList<>(); private final List hidePackets = new ArrayList<>(); private final List metaPackets = new ArrayList<>(); - private static final double DELTA = 0.3; - - // Classes: - private static final Class CHAT_COMPONENT_TEXT_CLAZZ = Reflection.getMinecraftClass("ChatComponentText"); - private static final Class CHAT_BASE_COMPONENT_CLAZZ = Reflection.getMinecraftClass("IChatBaseComponent"); - private static final Class ENTITY_ARMOR_STAND_CLAZZ = Reflection.getMinecraftClass("EntityArmorStand"); - private static final Class ENTITY_LIVING_CLAZZ = Reflection.getMinecraftClass("EntityLiving"); - private static final Class ENTITY_CLAZZ = Reflection.getMinecraftClass("Entity"); - private static final Class CRAFT_BUKKIT_CLASS = Reflection.getCraftBukkitClass("CraftWorld"); - private static final Class CRAFT_PLAYER_CLAZZ = Reflection.getCraftBukkitClass("entity.CraftPlayer"); - private static final Class PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLAZZ = Reflection.getMinecraftClass( - "PacketPlayOutSpawnEntityLiving"); - private static final Class PACKET_PLAY_OUT_ENTITY_DESTROY_CLAZZ = Reflection.getMinecraftClass( - "PacketPlayOutEntityDestroy"); - private static final Class PACKET_PLAY_OUT_ENTITY_METADATA_CLAZZ = Reflection.getMinecraftClass( - "PacketPlayOutEntityMetadata"); - private static final Class DATAWATCHER_CLAZZ = Reflection.getMinecraftClass("DataWatcher"); - private static final Class ENTITY_PLAYER_CLAZZ = Reflection.getMinecraftClass("EntityPlayer"); - private static final Class PLAYER_CONNECTION_CLAZZ = Reflection.getMinecraftClass("PlayerConnection"); - private static final Class PACKET_CLAZZ = Reflection.getMinecraftClass("Packet"); - - // Constructors: - private static final Reflection.ConstructorInvoker CHAT_COMPONENT_TEXT_CONSTRUCTOR = Reflection - .getConstructor(CHAT_COMPONENT_TEXT_CLAZZ, String.class); - private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CONSTRUCTOR = Reflection - .getConstructor(PACKET_PLAY_OUT_SPAWN_ENTITY_LIVING_CLAZZ, ENTITY_LIVING_CLAZZ); - private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_ENTITY_DESTROY_CONSTRUCTOR = Reflection - .getConstructor(PACKET_PLAY_OUT_ENTITY_DESTROY_CLAZZ, int[].class); - private static final Reflection.ConstructorInvoker PACKET_PLAY_OUT_ENTITY_METADATA_CONSTRUCTOR = Reflection - .getConstructor(PACKET_PLAY_OUT_ENTITY_METADATA_CLAZZ, int.class, DATAWATCHER_CLAZZ, boolean.class); - - // Fields: - private static final Reflection.FieldAccessor playerConnectionField = Reflection.getField(ENTITY_PLAYER_CLAZZ, - "playerConnection", PLAYER_CONNECTION_CLAZZ); - - // Methods: - private static final Reflection.MethodInvoker SET_LOCATION_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "setLocation", double.class, double.class, double.class, float.class, float.class); - private static final Reflection.MethodInvoker SET_SMALL_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "setSmall", boolean.class); - private static final Reflection.MethodInvoker SET_INVISIBLE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "setInvisible", boolean.class); - private static final Reflection.MethodInvoker SET_BASE_PLATE_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "setBasePlate", boolean.class); - private static final Reflection.MethodInvoker SET_ARMS_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "setArms", boolean.class); - private static final Reflection.MethodInvoker PLAYER_GET_HANDLE_METHOD = Reflection.getMethod(CRAFT_PLAYER_CLAZZ, - "getHandle"); - private static final Reflection.MethodInvoker SEND_PACKET_METHOD = Reflection.getMethod(PLAYER_CONNECTION_CLAZZ, - "sendPacket", PACKET_CLAZZ); - private static final Reflection.MethodInvoker GET_ID_METHOD = Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, - "getId"); - private static final Reflection.MethodInvoker GET_DATAWATCHER_METHOD = Reflection.getMethod(ENTITY_CLAZZ, - "getDataWatcher"); - private final MinecraftVersion version; private final Location start; private final Object worldServer; @@ -86,24 +86,20 @@ public class Hologram { this.start = location; this.text = text; - this.worldServer = Reflection.getMethod(CRAFT_BUKKIT_CLASS, "getHandle") - .invoke(CRAFT_BUKKIT_CLASS.cast(location.getWorld())); + this.worldServer = Reflection.getMethod(CRAFT_WORLD_CLASS, "getHandle").invoke(location.getWorld()); createPackets(); } private void createPackets() { Reflection.MethodInvoker gravityMethod = (version.isAboveOrEqual(MinecraftVersion.V1_10_R1) ? - Reflection.getMethod(ENTITY_CLAZZ, "setNoGravity", boolean.class) : - Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setGravity", boolean.class)); + Reflection.getMethod(ENTITY_CLASS, "setNoGravity", boolean.class) : + Reflection.getMethod(ENTITY_ARMOR_STAND_CLASS, "setGravity", boolean.class)); - Reflection.MethodInvoker customNameMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) - ? Reflection.getMethod(ENTITY_CLAZZ, "setCustomName", version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_BASE_COMPONENT_CLAZZ : String.class) - : Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setCustomName", String.class)); + Reflection.MethodInvoker customNameMethod = Reflection.getMethod(ENTITY_CLASS, "setCustomName", + version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_BASE_COMPONENT_CLASS : String.class); - Reflection.MethodInvoker customNameVisibilityMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) ? - Reflection.getMethod(ENTITY_CLAZZ, "setCustomNameVisible", boolean.class) : - Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setCustomNameVisible", boolean.class)); + Reflection.MethodInvoker customNameVisibilityMethod = Reflection.getMethod(ENTITY_CLASS, "setCustomNameVisible", boolean.class); Location location = start.clone().add(0, DELTA * text.size(), 0); Class worldClass = worldServer.getClass().getSuperclass(); @@ -113,8 +109,8 @@ public class Hologram { } Reflection.ConstructorInvoker entityArmorStandConstructor = (version.isAboveOrEqual(MinecraftVersion.V1_14_R1) ? - Reflection.getConstructor(ENTITY_ARMOR_STAND_CLAZZ, worldClass, double.class, double.class, double.class) : - Reflection.getConstructor(ENTITY_ARMOR_STAND_CLAZZ, worldClass)); + Reflection.getConstructor(ENTITY_ARMOR_STAND_CLASS, worldClass, double.class, double.class, double.class) : + Reflection.getConstructor(ENTITY_ARMOR_STAND_CLASS, worldClass)); for (String line : text) { Object entityArmorStand = (version.isAboveOrEqual(MinecraftVersion.V1_14_R1) ? @@ -157,9 +153,8 @@ public class Hologram { throw new IllegalArgumentException("When updating the text, the old and new text should have the same amount of lines"); } - Reflection.MethodInvoker customNameMethod = (version.isAboveOrEqual(MinecraftVersion.V1_12_R1) - ? Reflection.getMethod(ENTITY_CLAZZ, "setCustomName", version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_BASE_COMPONENT_CLAZZ : String.class) - : Reflection.getMethod(ENTITY_ARMOR_STAND_CLAZZ, "setCustomName", String.class)); + Reflection.MethodInvoker customNameMethod = Reflection.getMethod(ENTITY_CLASS, "setCustomName", + version.isAboveOrEqual(MinecraftVersion.V1_13_R1) ? CHAT_BASE_COMPONENT_CLASS : String.class); for (int i = 0; i < text.size(); i++) { Object entityArmorStand = armorStands.get(i); @@ -190,8 +185,7 @@ public class Hologram { } public void update(Player player, List updatePackets) { - Object playerConnection = playerConnectionField.get(PLAYER_GET_HANDLE_METHOD - .invoke(CRAFT_PLAYER_CLAZZ.cast(player))); + Object playerConnection = PLAYER_CONNECTION_FIELD.get(PLAYER_GET_HANDLE_METHOD.invoke(player)); for (Object packet : updatePackets) { SEND_PACKET_METHOD.invoke(playerConnection, packet); @@ -199,8 +193,7 @@ public class Hologram { } public void show(Player player) { - Object playerConnection = playerConnectionField.get(PLAYER_GET_HANDLE_METHOD - .invoke(CRAFT_PLAYER_CLAZZ.cast(player))); + Object playerConnection = PLAYER_CONNECTION_FIELD.get(PLAYER_GET_HANDLE_METHOD.invoke(player)); for (int i = 0; i < text.size(); i++) { if (text.get(i).isEmpty()) continue; // No need to spawn the line. @@ -212,8 +205,7 @@ public class Hologram { } public void hide(Player player) { - Object playerConnection = playerConnectionField.get(PLAYER_GET_HANDLE_METHOD - .invoke(CRAFT_PLAYER_CLAZZ.cast(player))); + Object playerConnection = PLAYER_CONNECTION_FIELD.get(PLAYER_GET_HANDLE_METHOD.invoke(player)); for (int i = 0; i < text.size(); i++) { if (text.get(i).isEmpty()) continue; // No need to hide the line (as it was never spawned). diff --git a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java index 3c01e0f..b090c8a 100755 --- a/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java +++ b/nms/v1_8_R2/src/main/java/net/jitse/npclib/nms/v1_8_R2/NPC_v1_8_R2.java @@ -97,8 +97,11 @@ public class NPC_v1_8_R2 extends NPCBase { public void sendEquipmentPacket(Player player, NPCSlot slot, boolean auto) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - if (slot == NPCSlot.OFFHAND && !auto) { - throw new UnsupportedOperationException("Offhand is not supported on servers below 1.9"); + if (slot == NPCSlot.OFFHAND) { + if (!auto) { + throw new UnsupportedOperationException("Offhand is not supported on servers below 1.9"); + } + return; } ItemStack item = getItem(slot); diff --git a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java index 61961de..c2dea9f 100755 --- a/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java +++ b/nms/v1_8_R3/src/main/java/net/jitse/npclib/nms/v1_8_R3/NPC_v1_8_R3.java @@ -98,8 +98,11 @@ public class NPC_v1_8_R3 extends NPCBase { public void sendEquipmentPacket(Player player, NPCSlot slot, boolean auto) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; - if (slot == NPCSlot.OFFHAND && !auto) { - throw new UnsupportedOperationException("Offhand is not supported on servers below 1.9"); + if (slot == NPCSlot.OFFHAND) { + if (!auto) { + throw new UnsupportedOperationException("Offhand is not supported on servers below 1.9"); + } + return; } ItemStack item = getItem(slot);