Hey this util does JSON messages with multiple json strings in one message. After seeing @xTechno_'s thread (this) it made me want to do JSON messages with multiple events in one message. Here it is: Code (Move your mouse to reveal the content) Code (open) Code (close) Code: import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class Jinx { private static Class<?> _CRAFTPLAYER_CLASS; private static Constructor<?> _PACKET_PLAY_OUT_CHAT_CONSTRUCTOR; private static Method _A_METHOD, _GETHANDLE_METHOD, _SEND_PACKET_METHOD; private static Field _PLAYER_CONNECTION_FIELD; private static final HoverEvent _BLANK_HOVER_EVENT; private static final ClickEvent _BLANK_CLICK_EVENT; private static final Jinx _JINX; static { String name = Bukkit.getServer().getClass().getName(); name = name.substring(name.indexOf("craftbukkit.") + "craftbukkit.".length()); final String _VERSION = name.substring(0, name.indexOf(".")); try { Class<?> _ICHAT_BASE_COMPONENT_CLASS = Class .forName("net.minecraft.server." + _VERSION + ".IChatBaseComponent"); Class<?> _PACKET_PLAY_OUT_CHAT_CLASS = Class .forName("net.minecraft.server." + _VERSION + ".PacketPlayOutChat"); _CRAFTPLAYER_CLASS = Class.forName("org.bukkit.craftbukkit." + _VERSION + ".entity.CraftPlayer"); Class<?> _ENTITYPLAYER_CLASS = Class.forName("net.minecraft.server." + _VERSION + ".EntityPlayer"); Class<?> _PLAYER_CONNECTION_CLASS = Class.forName("net.minecraft.server." + _VERSION + ".PlayerConnection"); _PACKET_PLAY_OUT_CHAT_CONSTRUCTOR = _PACKET_PLAY_OUT_CHAT_CLASS.getConstructor(_ICHAT_BASE_COMPONENT_CLASS); _A_METHOD = Class.forName("net.minecraft.server." + _VERSION + ".IChatBaseComponent$ChatSerializer") .getMethod("a", String.class); _GETHANDLE_METHOD = _CRAFTPLAYER_CLASS.getMethod("getHandle"); _SEND_PACKET_METHOD = _PLAYER_CONNECTION_CLASS.getMethod("sendPacket", Class.forName("net.minecraft.server." + _VERSION + ".Packet")); _PLAYER_CONNECTION_FIELD = _ENTITYPLAYER_CLASS.getDeclaredField("playerConnection"); } catch (Exception ex) { ex.printStackTrace(); } _BLANK_HOVER_EVENT = new HoverEvent(null, ""); _BLANK_CLICK_EVENT = new ClickEvent("", ""); _JINX = new Jinx(); } private Jinx() { } public static class JSONMessage { private List<MessagePart> _messageParts; private String _message; private boolean _compiled; { this._messageParts = new ArrayList<>(); this._compiled = false; } public JSONMessage() { this._compiled = true; } public JSONMessage(String msg) { this._messageParts.add(_JINX.new MessagePart(msg)); } public JSONMessage(String msg, HoverEvent hoverEvent) { this._messageParts.add(_JINX.new MessagePart(msg, hoverEvent)); } public JSONMessage(String msg, ClickEvent clickEvent) { this._messageParts.add(_JINX.new MessagePart(msg, clickEvent)); } public JSONMessage(String msg, HoverEvent hoverEvent, ClickEvent clickEvent) { this._messageParts.add(_JINX.new MessagePart(msg, hoverEvent, clickEvent)); } public JSONMessage append(String msg) { this._messageParts.add(_JINX.new MessagePart(msg)); this._compiled = false; return this; } public JSONMessage append(String msg, HoverEvent hoverEvent) { this._messageParts.add(_JINX.new MessagePart(msg, hoverEvent)); this._compiled = false; return this; } public JSONMessage append(String msg, ClickEvent clickEvent) { this._messageParts.add(_JINX.new MessagePart(msg, clickEvent)); this._compiled = false; return this; } public JSONMessage append(String msg, HoverEvent hoverEvent, ClickEvent clickEvent) { this._messageParts.add(_JINX.new MessagePart(msg, hoverEvent, clickEvent)); this._compiled = false; return this; } @SuppressWarnings("deprecation") private String compile() { StringBuilder sb = new StringBuilder("["); boolean hadHoverEvent = false, hadClickEvent = false; for (MessagePart part : this._messageParts) { sb.append(",{\"text\":\"" + part._msg + "\""); HoverEvent hoverEvent = part._hoverEvent; if (hoverEvent._type.equals(HoverEvent.SHOW_TEXT)) { sb.append(",\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"" + part._hoverEvent._value + "\"}}"); hadHoverEvent = true; } else if (hoverEvent._type.equals(HoverEvent.SHOW_ACHIEVEMENT)) { sb.append(",\"hoverEvent\":{\"action\":\"show_achievement\",\"value\":\"achievement." + hoverEvent._value + "\"}}"); hadHoverEvent = true; } else if (hoverEvent._type.equals(HoverEvent.SHOW_STATISTIC)) { sb.append(",\"hoverEvent\":{\"action\":\"show_achievement\",\"value\":\"achievement." + hoverEvent._value + "\"}}"); hadHoverEvent = true; } else if (hoverEvent._type.equals(HoverEvent.SHOW_ITEM)) { ItemStack item = ((ItemStack) part._hoverEvent._value).clone(); String name = item.hasItemMeta() ? item.getType().toString().toLowerCase() : item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : item.getType().toString().toLowerCase(); sb.append(",\"hoverEvent\":{\"action\":\"show_item\",\"value\":\"{id:minecraft:" + item.getType().toString().toLowerCase() + ",Count:" + item.getAmount() + "b"); if (item.hasItemMeta()) { if ((item.getItemMeta().hasDisplayName()) || ((item.getItemMeta().hasLore()) && (item.getItemMeta().getLore().size() > 0))) { sb.append(",tag:{display:{"); } if (item.getItemMeta().hasDisplayName()) { sb.append("Name:" + name); } if ((item.getItemMeta().hasLore()) && (item.getItemMeta().getLore().size() > 0)) { sb.append(",Lore:["); boolean firstLore = true; for (String lore : item.getItemMeta().getLore()) { if (!firstLore) { sb.append("," + lore); } else { sb.append(lore); firstLore = false; } } sb.append("]"); } if ((item.getItemMeta().hasDisplayName()) || ((item.getItemMeta().hasLore()) && (item.getItemMeta().getLore().size() > 0))) { if (item.getEnchantments().size() > 0) { sb.append("},ench:["); boolean firstEnchant = true; for (Enchantment enchant : item.getEnchantments().keySet()) { if (!firstEnchant) { sb.append(",{id:" + enchant.getId() + ",lvl:" + item.getEnchantments().get(enchant) + "}"); } else { sb.append("{id:" + enchant.getId() + ",lvl:" + item.getEnchantments().get(enchant) + "}"); firstEnchant = false; } } sb.append("]}"); } else { sb.append("}}"); } } } if ((item.getEnchantments().size() > 0) && (!sb.toString().contains("},ench:["))) { sb.append(",tag:{ench:["); boolean firstEnchant = true; for (Enchantment enchant : item.getEnchantments().keySet()) { if (!firstEnchant) { sb.append(",{id:" + enchant.getId() + ",lvl:" + item.getEnchantments().get(enchant) + "}"); } else { sb.append( "{id:" + enchant.getId() + ",lvl:" + item.getEnchantments().get(enchant) + "}"); firstEnchant = false; } } sb.append("]}"); } sb.append("}\"}"); hadHoverEvent = true; } else if (hoverEvent._type.equals(HoverEvent.SHOW_ENTITY)) { Entity entity = (Entity) hoverEvent._value; sb.append(",\"hoverEvent\":{\"action\":\"show_entity\",\"value\":\"{name:\"" + entity.getCustomName() + "\", type:\"" + entity.getName() + "\", id:\"" + entity.getUniqueId().toString() + "\"}}"); hadHoverEvent = true; } else { if (hadHoverEvent) { sb.append(",\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\"}}"); } } if (!part._clickEvent._value.equals("")) { sb.append(",\"clickEvent\":{\"action\":\"" + part._clickEvent._type + "\",\"value\":\"" + part._clickEvent._value + "\"}"); hadClickEvent = true; } else { if (hadClickEvent) { sb.append(",\"clickEvent\":{\"action\":\"suggest_command\",\"value\":\"\"}"); } } sb.append("}"); } this._message = sb.toString().replaceFirst(",", "") + "]"; this._compiled = true; return this._message; } public void sendMessage(Player player) { if (!this._compiled) { compile(); } try { Object messageComponent = _A_METHOD.invoke(null, this._message); Object packet = _PACKET_PLAY_OUT_CHAT_CONSTRUCTOR.newInstance(messageComponent); Object craftPlayer = _CRAFTPLAYER_CLASS.cast(player); Object entityPlayer = _GETHANDLE_METHOD.invoke(craftPlayer); Object playerConnection = _PLAYER_CONNECTION_FIELD.get(entityPlayer); _SEND_PACKET_METHOD.invoke(playerConnection, packet); } catch (Exception ex) { ex.printStackTrace(); } } } private class MessagePart { private String _msg; private ClickEvent _clickEvent; private HoverEvent _hoverEvent; { this._hoverEvent = _BLANK_HOVER_EVENT; this._clickEvent = _BLANK_CLICK_EVENT; } public MessagePart(String msg) { this._msg = ChatColor.translateAlternateColorCodes('&', msg + "&r"); } public MessagePart(String msg, Jinx.HoverEvent hoverEvent) { this._msg = ChatColor.translateAlternateColorCodes('&', msg + "&r"); this._hoverEvent = hoverEvent; } public MessagePart(String msg, Jinx.ClickEvent clickEvent) { this._msg = ChatColor.translateAlternateColorCodes('&', msg + "&r"); this._clickEvent = clickEvent; } public MessagePart(String msg, HoverEvent hoverEvent, ClickEvent clickEvent) { this._msg = ChatColor.translateAlternateColorCodes('&', msg + "&r"); this._hoverEvent = hoverEvent; this._clickEvent = clickEvent; } } public static class HoverEvent { public static final String SHOW_TEXT, SHOW_ACHIEVEMENT, SHOW_STATISTIC, SHOW_ITEM, SHOW_ENTITY; static { SHOW_TEXT = "show_text"; SHOW_ACHIEVEMENT = "show_achievement"; SHOW_STATISTIC = "show_statistic"; SHOW_ITEM = "show_item"; SHOW_ENTITY = "show_entity"; } private Object _value; private String _type; public HoverEvent(String value) { this._value = ChatColor.translateAlternateColorCodes('&', value + "&r"); this._type = SHOW_TEXT; } public HoverEvent(Object value, String type) { if (value instanceof String) { this._value = ChatColor.translateAlternateColorCodes('&', value + "&r"); } else { this._value = value; } this._type = type; } } public static class ClickEvent { public static final String OPEN_URL, RUN_COMMAND, SUGGEST_COMMAND; static { OPEN_URL = "open_url"; RUN_COMMAND = "run_command"; SUGGEST_COMMAND = "suggest_command"; } private String _value; private String _type; public ClickEvent(String value, String type) { this._value = ChatColor.translateAlternateColorCodes('&', value + "&r"); this._type = type; } } } This is an example code: Example (Move your mouse to reveal the content) Example (open) Example (close) Code: JSONMessage message = new JSONMessage(); message.append("This is hoverable", new HoverEvent("Hovered me")); message.append(" "); message.append("This is clickable", new ClickEvent("Test", ClickEvent.SUGGEST_COMMAND)); message.append(" "); message.append("This is both", new HoverEvent(new ItemStack(Material.IRON_SWORD), HoverEvent.SHOW_ITEM), new ClickEvent("This is a sword!", ClickEvent.SUGGEST_COMMAND)); for (Player player : Bukkit.getOnlinePlayers()) { message.sendMessage(player); } All hover events: Spoiler (Move your mouse to the spoiler area to reveal the content) Show Spoiler Hide Spoiler SHOW_TEXT, SHOW_ACHIEVEMENT, SHOW_STATISTIC, SHOW_ITEM, SHOW_ENTITY All click events: Spoiler (Move your mouse to the spoiler area to reveal the content) Show Spoiler Hide Spoiler OPEN_URL, RUN_COMMAND, SUGGEST_COMMAND Within the class Jinx: public static class JSONMessage = Used to create JSONMessages JSONMessage(String msg) = Starts it off with the plain message JSONMessage(String msg, HoverEvent hoverEvent) = Msg + HoverEvent JSONMessage(String msg, ClickEvent clickEvent) = Msg + ClickEvent JSONMessage(String msg, HoverEvent hoverEvent, ClickEvent clickEvent) = Msg + Events JSONMessage append(String msg) = Adds a plain message JSONMessage append(String msg, HoverEvent hoverEvent) = Msg + HoverEvent JSONMessage append(String msg, ClickEvent clickEvent) = Msg + ClickEvent JSONMessage append(String msg, HoverEvent hoverEvent, ClickEvent clickEvent) = Msg + Events private class MessagePart = Used to store the parts in JSONMesssage Its methods/constructors you don't really need to know public static class HoverEvent = Used to make hover events HoverEvent(String value) = A SHOW_TEXT hoverevent HoverEvent(Object value, String type) You input the appropriate type for the value inputted (SHOW_ITEM = ItemStack, ect.)public static class ClickEvent = Used to make click events ClickEvent(String value, String type) = Makes a ClickEvent with the type public static final fields available incase you don't know for HoverEvent and ClickEvent. Color code compatibility with & symbols. Finally thanks to @xTechno_ again bc without them this thread wouldn't of happened