package tntrun.utils; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import tntrun.TNTRun; public class ActionBar { private Class<?> nmsChatSerializer; private Class<?> nmsTitleAction; private Class<?> nmsPacketTitle; private Class<?> nmsPacketChat; private Class<?> nmsChatBaseComponent; private Object nmsIChatBaseComponent; private final String networkManager = "networkManager"; private final String handle = "getHandle"; private final String playerConnection = "playerConnection"; private final String sendPacket = "sendPacket"; private void loadClasses(){ nmsIChatBaseComponent = getNMSClass("IChatBaseComponent"); nmsPacketChat = getNMSClass("PacketPlayOutChat"); nmsChatBaseComponent = getNMSClass("IChatBaseComponent"); if (getVersion().contains("1_7")) { nmsChatSerializer = getNMSClass("ChatSerializer"); } else if (getVersion().contains("1_8")) { if (getVersion().contains("R1")) { nmsChatSerializer = getNMSClass("ChatSerializer"); nmsPacketTitle = getNMSClass("PacketPlayOutTitle"); nmsTitleAction = getNMSClass("EnumTitleAction"); } else if (getVersion().contains("R2") || getVersion().contains("R3")) { nmsChatSerializer = getNMSClass("IChatBaseComponent$ChatSerializer"); nmsPacketTitle = getNMSClass("PacketPlayOutTitle"); nmsTitleAction = getNMSClass("PacketPlayOutTitle$EnumTitleAction"); } }else if(getVersion().contains("1_9")){ nmsChatSerializer = getNMSClass("IChatBaseComponent$ChatSerializer"); nmsPacketTitle = getNMSClass("PacketPlayOutTitle"); nmsTitleAction = getNMSClass("PacketPlayOutTitle$EnumTitleAction"); } } public Class<?> getNMSChatSerializer() { return nmsChatSerializer; } public Class<?> getNMSIChatBaseComponent() { return nmsIChatBaseComponent.getClass(); } public Class<?> getNMSPacketTitle() { return nmsPacketTitle; } public void sendActionBar(Player player, String message) { loadClasses(); try { Object handle = getMethod(player.getClass(), this.handle, new Class[0]).invoke(player, new Object[0]); Object playerConnection = getField(handle.getClass(), this.playerConnection).get(handle); Object serializedMessage = getMethod(this.nmsChatSerializer, "a", String.class).invoke(this.nmsChatSerializer, "{\"text\":\"" + message + "\"}"); Object packet = null; if (getVersion().contains("1_7")) { packet = this.nmsPacketChat.getConstructor(this.nmsChatBaseComponent, Integer.class).newInstance(serializedMessage, (int) 2); } else if (getVersion().contains("1_8") || getVersion().contains("1_9")) { packet = this.nmsPacketChat.getConstructor(this.nmsChatBaseComponent, byte.class).newInstance(serializedMessage, (byte) 2); } getMethod(playerConnection.getClass(), this.sendPacket).invoke(playerConnection, packet); } catch (Exception localException) { localException.printStackTrace(); } } private final Map<Class<?>, Class<?>> CORRESPONDING_TYPES = new HashMap<Class<?>, Class<?>>(); private Class<?> getPrimitiveType(Class<?> clazz) { return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES .get(clazz) : clazz; } private Class<?>[] toPrimitiveTypeArray(Class<?>[] classes) { int a = classes != null ? classes.length : 0; Class<?>[] types = new Class<?>[a]; for (int i = 0; i < a; i++) types[i] = getPrimitiveType(classes[i]); return types; } private boolean equalsTypeArray(Class<?>[] a, Class<?>[] o) { if (a.length != o.length) return false; for (int i = 0; i < a.length; i++) if (!a[i].equals(o[i]) && !a[i].isAssignableFrom(o[i])) return false; return true; } private Object getHandle(Object obj) { try { return getMethod("getHandle", obj.getClass()).invoke(obj); } catch (Exception e) { e.printStackTrace(); return null; } } private Method getMethod(String name, Class<?> clazz, Class<?>... paramTypes) { Class<?>[] t = toPrimitiveTypeArray(paramTypes); for (Method m : clazz.getMethods()) { Class<?>[] types = toPrimitiveTypeArray(m.getParameterTypes()); if (m.getName().equals(name) && equalsTypeArray(types, t)) return m; } return null; } public static String getVersion() { String name = Bukkit.getServer().getClass().getPackage().getName(); String version = name.substring(name.lastIndexOf('.') + 1) + "."; return version; } private Class<?> getNMSClass(String className) { String fullName = "net.minecraft.server." + getVersion() + className; Class<?> clazz = null; try { clazz = Class.forName(fullName); } catch (Exception e) { e.printStackTrace(); } return clazz; } private Field getField(Class<?> clazz, String name) { try { Field field = clazz.getDeclaredField(name); field.setAccessible(true); return field; } catch (Exception e) { e.printStackTrace(); return null; } } private Method getMethod(Class<?> clazz, String name, Class<?>... args) { for (Method m : clazz.getMethods()) if (m.getName().equals(name) && (args.length == 0 || ClassListEqual(args, m.getParameterTypes()))) { m.setAccessible(true); return m; } return null; } private boolean ClassListEqual(Class<?>[] l1, Class<?>[] l2) { boolean equal = true; if (l1.length != l2.length) return false; for (int i = 0; i < l1.length; i++) if (l1[i] != l2[i]) { equal = false; break; } return equal; } }