private void send(CommandSender sender, String jsonString) { if (!(sender instanceof Player)) { sender.sendMessage(toOldMessageFormat()); return; } Player player = (Player) sender; try { Object handle = Reflection.getHandle(player); Object connection = Reflection.getField(handle.getClass(), "playerConnection").get(handle); Reflection.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet")) .invoke(connection, createChatPacket(jsonString)); } catch (IllegalArgumentException e) { Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); } catch (IllegalAccessException e) { Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); } catch (InstantiationException e) { Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e); } catch (InvocationTargetException e) { Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e); } catch (NoSuchMethodException e) { Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e); } catch (ClassNotFoundException e) { Bukkit.getLogger().log(Level.WARNING, "Could not find class.", e); } }
/** * Set the behavior of the current editing component to display information about a statistic * parameter with an entity type when the client hovers over the text. * * <p>Tooltips do not inherit display characteristics, such as color and styles, from the message * component on which they are applied. * * @param which The statistic to display. * @param entity The sole entity type parameter to the statistic. * @return This builder instance. * @exception IllegalArgumentException If the statistic requires a parameter which was not * supplied, or was supplied a parameter that was not required. */ public FancyMessage statisticTooltip(final Statistic which, EntityType entity) { Type type = which.getType(); if (type == Type.UNTYPED) { throw new IllegalArgumentException("That statistic needs no additional parameter!"); } if (type != Type.ENTITY) { throw new IllegalArgumentException( "Wrong parameter type for that statistic - needs " + type + "!"); } try { Object statistic = Reflection.getMethod( Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic", Statistic.class, EntityType.class) .invoke(null, which, entity); return achievementTooltip( (String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic)); } catch (IllegalAccessException e) { Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); return this; } catch (IllegalArgumentException e) { Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); return this; } catch (InvocationTargetException e) { Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e); return this; } }
private Object createChatPacket(String json) throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { if (nmsChatSerializerGsonInstance == null) { // Find the field and its value, completely bypassing obfuscation Class<?> chatSerializerClazz; String version = Reflection.getVersion(); double majorVersion = Double.parseDouble(version.replace('_', '.').substring(1, 4)); int lesserVersion = Integer.parseInt(version.substring(6, 7)); if (majorVersion < 1.8 || (majorVersion == 1.8 && lesserVersion == 1)) { chatSerializerClazz = Reflection.getNMSClass("ChatSerializer"); } else { chatSerializerClazz = Reflection.getNMSClass("IChatBaseComponent$ChatSerializer"); } if (chatSerializerClazz == null) { throw new ClassNotFoundException("Can't find the ChatSerializer class"); } for (Field declaredField : chatSerializerClazz.getDeclaredFields()) { if (Modifier.isFinal(declaredField.getModifiers()) && Modifier.isStatic(declaredField.getModifiers()) && declaredField.getType().getName().endsWith("Gson")) { // We've found our field declaredField.setAccessible(true); nmsChatSerializerGsonInstance = declaredField.get(null); fromJsonMethod = nmsChatSerializerGsonInstance .getClass() .getMethod("fromJson", String.class, Class.class); break; } } } // Since the method is so simple, and all the obfuscated methods have the same name, it's easier // to reimplement 'IChatBaseComponent a(String)' than to reflectively call it // Of course, the implementation may change, but fuzzy matches might break with signature // changes Object serializedChatComponent = fromJsonMethod.invoke( nmsChatSerializerGsonInstance, json, Reflection.getNMSClass("IChatBaseComponent")); return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent); }
/** * Set the behavior of the current editing component to display information about an item when the * client hovers over the text. * * <p>Tooltips do not inherit display characteristics, such as color and styles, from the message * component on which they are applied. * * @param itemStack The stack for which to display information. * @return This builder instance. */ public FancyMessage itemTooltip(final ItemStack itemStack) { try { Object nmsItem = Reflection.getMethod( Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class) .invoke(null, itemStack); return itemTooltip( Reflection.getMethod( Reflection.getNMSClass("ItemStack"), "save", Reflection.getNMSClass("NBTTagCompound")) .invoke(nmsItem, Reflection.getNMSClass("NBTTagCompound").newInstance()) .toString()); } catch (Exception e) { e.printStackTrace(); return this; } }
public FancyMessage(final TextualComponent firstPartText) { messageParts = new ArrayList<MessagePart>(); messageParts.add(new MessagePart(firstPartText)); jsonString = null; dirty = false; if (nmsPacketPlayOutChatConstructor == null) { try { nmsPacketPlayOutChatConstructor = Reflection.getNMSClass("PacketPlayOutChat") .getDeclaredConstructor(Reflection.getNMSClass("IChatBaseComponent")); nmsPacketPlayOutChatConstructor.setAccessible(true); } catch (NoSuchMethodException e) { Bukkit.getLogger().log(Level.SEVERE, "Could not find Minecraft method or constructor.", e); } catch (SecurityException e) { Bukkit.getLogger().log(Level.WARNING, "Could not access constructor.", e); } } }
/** * Set the behavior of the current editing component to display information about an achievement * when the client hovers over the text. * * <p>Tooltips do not inherit display characteristics, such as color and styles, from the message * component on which they are applied. * * @param which The achievement to display. * @return This builder instance. */ public FancyMessage achievementTooltip(final Achievement which) { try { Object achievement = Reflection.getMethod( Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class) .invoke(null, which); return achievementTooltip( (String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name").get(achievement)); } catch (IllegalAccessException e) { Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e); return this; } catch (IllegalArgumentException e) { Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e); return this; } catch (InvocationTargetException e) { Bukkit.getLogger().log(Level.WARNING, "A error has occured durring invoking of method.", e); return this; } }